mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-08 17:03:11 +02:00
Merge pull request #13054 from AndrewMeadows/workload-012
workload: yield simulation ownership of objects outside nearby region
This commit is contained in:
commit
3c2595869b
5 changed files with 109 additions and 79 deletions
|
@ -360,7 +360,12 @@ bool EntityTree::updateEntity(EntityItemPointer entity, const EntityItemProperti
|
|||
// the sender is trying to take or continue ownership
|
||||
if (entity->getSimulatorID().isNull()) {
|
||||
// the sender is taking ownership
|
||||
properties.promoteSimulationPriority(RECRUIT_SIMULATION_PRIORITY);
|
||||
SimulationOwner owner = properties.getSimulationOwner();
|
||||
if (owner.getPriority() == VOLUNTEER_SIMULATION_PRIORITY) {
|
||||
// the entity-server always promotes VOLUNTEER to RECRUIT to avoid ownership thrash
|
||||
// when dynamic objects first activate and multiple participants bid simultaneously
|
||||
properties.promoteSimulationPriority(RECRUIT_SIMULATION_PRIORITY);
|
||||
}
|
||||
simulationBlocked = false;
|
||||
} else if (entity->getSimulatorID() == senderID) {
|
||||
// the sender is asserting ownership, maybe changing priority
|
||||
|
@ -392,6 +397,7 @@ bool EntityTree::updateEntity(EntityItemPointer entity, const EntityItemProperti
|
|||
}
|
||||
if (simulationBlocked) {
|
||||
// squash ownership and physics-related changes.
|
||||
// TODO? replace these eight calls with just one?
|
||||
properties.setSimulationOwnerChanged(false);
|
||||
properties.setPositionChanged(false);
|
||||
properties.setRotationChanged(false);
|
||||
|
@ -1795,7 +1801,7 @@ void EntityTree::addToNeedsParentFixupList(EntityItemPointer entity) {
|
|||
|
||||
void EntityTree::update(bool simulate) {
|
||||
PROFILE_RANGE(simulation_physics, "UpdateTree");
|
||||
PerformanceTimer perfTimer("UpdateTreen");
|
||||
PerformanceTimer perfTimer("updateTree");
|
||||
withWriteLock([&] {
|
||||
fixupNeedsParentFixups();
|
||||
if (simulate && _simulation) {
|
||||
|
|
|
@ -19,74 +19,75 @@
|
|||
#include <UUID.h>
|
||||
|
||||
// HighFidelity uses a distributed physics simulation where multiple "participants" simulate portions
|
||||
// of the same world. When portions overlap only one participant is allowed to be the authority for any
|
||||
// particular object. For a simulated entity the authoritative participant is called the simulation "owner" and
|
||||
// their duty is to send transform/velocity updates for the entity to the central entity-server.
|
||||
// The entity-server relays updates to other participants who apply them as "state synchronization"
|
||||
// to their own simulation.
|
||||
// of the same domain. Even when portions overlap only one participant is allowed to be the current
|
||||
// authority for any particular object's physical simulation. The authoritative participant is called the
|
||||
// "simulation owner" and its duty is to send "state synchronization" (transform/velocity) updates for an
|
||||
// entity to the entity-server. The entity-server relays updates to other participants who apply them to
|
||||
// their own simulation.
|
||||
//
|
||||
// Participants acquire ownership by sending a "bid" to the entity-server. The bid is a properties update:
|
||||
// {
|
||||
// "simulationOwner": { "ownerID" : sessionID, "priority" : priority },
|
||||
// { "simulationOwner": { "ownerID" : sessionID, "priority" : priority },
|
||||
// transform/velocity properties
|
||||
// }
|
||||
//
|
||||
// The entity-server is the authority as to who owns what and may reject a bid.
|
||||
// The rules for handling a bid are as follows:
|
||||
// The entity-server is the authority as to who owns what and may reject a bid. The rules for handling a
|
||||
// bid are as follows:
|
||||
//
|
||||
// (1) A bid may be refused for special ownership restrictions, but otherwise...
|
||||
//
|
||||
// (2) A bid at higher priority is accepted
|
||||
//
|
||||
// (3) A bid at equal priority is rejected if receieved within a grace-period (200msec)
|
||||
// of the last ownership transition, otherwise it is accepted
|
||||
// (3) A bid at equal priority is accepted unless it was received shortly after (within 200msec) of the
|
||||
// last ownership change. This to avoid rapid ownership transitions should multiple participants
|
||||
// bid simultaneously.
|
||||
//
|
||||
// (4) The current owner is the only participant allowed to clear ownership (entity-server can override).
|
||||
// (4) The current owner is the only participant allowed to clear their ownership or adjust priority.
|
||||
//
|
||||
// (5) The current owner is the only participant allowed to adjust priority (entity-server can override).
|
||||
//
|
||||
// (6) If an owner does not update the transform or velocities of an owned entity within some period
|
||||
// (5) If an owner does not update the transform or velocities of an owned entity within some period
|
||||
// (5 seconds) then ownership is cleared and the entity's velocities are zeroed. This to handle
|
||||
// the case when an owner drops off the network.
|
||||
//
|
||||
// The priority of a participant's bid depends on how "interested" it is in the entity's motion. The rules
|
||||
// for bidding are as follows:
|
||||
//
|
||||
// (7) A participant (almost) never assumes that a bid is accepted by the entity-server. It packs the
|
||||
// simulation owner and priority as if they really did change but doesn't actually modify them
|
||||
// locally. Thus, if the bid packet is lost the participant will re-send after some period.
|
||||
// The participant only updates its knowledge of who owns what when it recieves an update from the
|
||||
// entity-server. An exception is when the participant creates a moving entity: it assumes it starts
|
||||
// off owning any moving entities it creates.
|
||||
// (6) A participant (almost) never assumes its bid is accepted by the entity-server. It packs the
|
||||
// simulation owner properties as if they really did change but doesn't actually modify them
|
||||
// locally. Instead it waits to hear back from the entity-server for bid acceptance. If the entity
|
||||
// remains unowned the participant will resend the bid (assuming the bid pakcet was lost). The
|
||||
// exception is when the participant creates a moving entity: it assumes it starts off owning any
|
||||
// moving entities it creates.
|
||||
//
|
||||
// (8) When an unowned entity becomes active in the physics simulation the participant will
|
||||
// start a timer and if the entity is still unowned after some period (0.5 seconds)
|
||||
// it will bid at priority = VOLUNTEER (=2). The entity-server never grants ownership at VOLUNTEER
|
||||
// (7) When an entity becomes active in the physics simulation but is not owned the participant will
|
||||
// start a timer and if it is still unowned after expiry (0.5 seconds) the participant will
|
||||
// bid at priority = VOLUNTEER (=2). The entity-server never grants ownership at VOLUNTEER
|
||||
// priority: when a VOLUNTEER bid is accepted the entity-server always promotes the priority to
|
||||
// RECRUIT (VOLUNTEER + 1); this to avoid a race-condition which might rapidly transition ownership
|
||||
// RECRUIT (=VOLUNTEER + 1); this to avoid a race-condition which might rapidly transition ownership
|
||||
// when multiple participants (with variable ping-times to the server) bid simultaneously for a
|
||||
// recently activated entity.
|
||||
//
|
||||
// (9) When a participant changes an entity's transform/velocity it will bid at priority = POKE (=127)
|
||||
// (8) When a participant's script changes an entity's transform/velocity the participant will bid at
|
||||
// priority = POKE (=127)
|
||||
//
|
||||
// (10) When an entity touches MyAvatar the participant it will bid at priority = POKE.
|
||||
// (9) When an entity collides against MyAvatar the participant will bid at priority = POKE.
|
||||
//
|
||||
// (11) When a participant grabs an entity it will bid at priority = GRAB (=128).
|
||||
// (10) When a participant grabs an entity it will bid at priority = GRAB (=128). This to allow UserA
|
||||
// to whack UserB with a "sword" without losing ownership, since UserB will bid at POKE. If UserB
|
||||
// wants to contest for ownership they must also GRAB it.
|
||||
//
|
||||
// (12) When entityA, locally owned at priority = N, collides with an unowned entityB the owner will
|
||||
// also bid for entityB at priority = N-1 (or VOLUNTEER, whichever is larger).
|
||||
// (11) When EntityA, locally owned at priority = N, collides with an unowned EntityB the owner will
|
||||
// also bid for EntityB at priority = N-1 (or VOLUNTEER, whichever is larger).
|
||||
//
|
||||
// (13) When an entity comes to rest and is deactivated in the physics simulation the owner will
|
||||
// send an update to: clear their ownerhsip, set priority to zero, and set the object's
|
||||
// velocities to be zero. As per a normal bid, the owner does NOT assume that its ownership
|
||||
// has been cleared until it hears from the entity-server. This, if the packet is lost the
|
||||
// owner will re-send after some period.
|
||||
// (12) When an entity comes to rest and is deactivated in the physics simulation the owner will send
|
||||
// an update to: clear their ownerhsip, set priority to zero, and set the entity's velocities to
|
||||
// zero. As per a normal bid, the owner does NOT assume its ownership has been cleared until
|
||||
// it hears back from the entity-server. Thus, if the packet is lost the owner will re-send after
|
||||
// expiry.
|
||||
//
|
||||
// (14) When an entity's ownership priority drops below VOLUNTEER other participants may bid for it
|
||||
// immediately at priority = VOLUNTEER.
|
||||
// (13) When an entity is still active but the owner no longer wants to own it, the owner will drop its
|
||||
// priority to YIELD (=1, below VOLUNTEER) thereby signalling to other participants to bid for it.
|
||||
//
|
||||
// (15) When an entity is still active but the owner no longer wants to own it, it will drop its priority
|
||||
// to YIELD (=1, less than VOLUNTEER) thereby signalling to other participants to bid for it.
|
||||
// (14) When an entity's ownership priority drops to YIELD (=1, below VOLUNTEER) other participants may
|
||||
// bid for it immediately at VOLUNTEER.
|
||||
//
|
||||
const uint8_t YIELD_SIMULATION_PRIORITY = 1;
|
||||
const uint8_t VOLUNTEER_SIMULATION_PRIORITY = YIELD_SIMULATION_PRIORITY + 1;
|
||||
|
|
|
@ -139,6 +139,7 @@ void EntityMotionState::handleEasyChanges(uint32_t& flags) {
|
|||
if (_entity->getSimulatorID().isNull()) {
|
||||
// simulation ownership has been removed
|
||||
if (glm::length2(_entity->getWorldVelocity()) == 0.0f) {
|
||||
// TODO: also check angularVelocity
|
||||
// this object is coming to rest --> clear the ACTIVATION flag and _bidPriority
|
||||
flags &= ~Simulation::DIRTY_PHYSICS_ACTIVATION;
|
||||
_body->setActivationState(WANTS_DEACTIVATION);
|
||||
|
@ -148,19 +149,21 @@ void EntityMotionState::handleEasyChanges(uint32_t& flags) {
|
|||
} else {
|
||||
// disowned object is still moving --> start timer for ownership bid
|
||||
// TODO? put a delay in here proportional to distance from object?
|
||||
upgradeBidPriority(VOLUNTEER_SIMULATION_PRIORITY);
|
||||
computeNewBidPriority(VOLUNTEER_SIMULATION_PRIORITY);
|
||||
_nextBidExpiry = usecTimestampNow() + USECS_BETWEEN_OWNERSHIP_BIDS;
|
||||
}
|
||||
_loopsWithoutOwner = 0;
|
||||
_numInactiveUpdates = 0;
|
||||
} else if (isLocallyOwned()) {
|
||||
// we just inherited ownership, make sure our desired priority matches what we have
|
||||
upgradeBidPriority(_entity->getSimulationPriority());
|
||||
// we just received ownership, or the priority of our existing ownership has changed
|
||||
computeNewBidPriority(_entity->getSimulationPriority());
|
||||
} else {
|
||||
// the entity is owned by someone else, so we clear _bidPriority here
|
||||
// but _bidPriority may be updated to non-zero value if this object interacts with locally owned simulation
|
||||
// in which case we may try to bid again
|
||||
_bidPriority = 0;
|
||||
// the entity is owned by someone else
|
||||
// we are always willing to volunteer for nearby objects
|
||||
// otherwise we zero _bidPriority here
|
||||
// (it's possible _bidPriority will be promoted in subsequent frames
|
||||
// when local scripts or owned simulation interact with it)
|
||||
_bidPriority = (_region == workload::Region::R1) ? VOLUNTEER_SIMULATION_PRIORITY : 0;
|
||||
_nextBidExpiry = usecTimestampNow() + USECS_BETWEEN_OWNERSHIP_BIDS;
|
||||
_numInactiveUpdates = 0;
|
||||
}
|
||||
|
@ -170,7 +173,7 @@ void EntityMotionState::handleEasyChanges(uint32_t& flags) {
|
|||
// (1) we own it but may need to change the priority OR...
|
||||
// (2) we don't own it but should bid (because a local script has been changing physics properties)
|
||||
uint8_t newPriority = isLocallyOwned() ? _entity->getSimulationOwner().getPriority() : _entity->getSimulationOwner().getPendingPriority();
|
||||
upgradeBidPriority(newPriority);
|
||||
computeNewBidPriority(newPriority);
|
||||
|
||||
// reset bid expiry so that we bid ASAP
|
||||
_nextBidExpiry = 0;
|
||||
|
@ -299,7 +302,7 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) {
|
|||
if (_entity->getSimulatorID().isNull()) {
|
||||
_loopsWithoutOwner++;
|
||||
if (_loopsWithoutOwner > LOOPS_FOR_SIMULATION_ORPHAN && usecTimestampNow() > _nextBidExpiry) {
|
||||
upgradeBidPriority(VOLUNTEER_SIMULATION_PRIORITY);
|
||||
computeNewBidPriority(VOLUNTEER_SIMULATION_PRIORITY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -326,21 +329,26 @@ void EntityMotionState::setShape(const btCollisionShape* shape) {
|
|||
}
|
||||
|
||||
bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
||||
// NOTE: we only get here if we think we own the simulation
|
||||
// NOTE: this method is only ever called when the entity simulation is locally owned
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, "CheckOutOfSync");
|
||||
|
||||
// Since we own the simulation: make sure _bidPriority is not less than current owned priority
|
||||
// because: an _bidPriority of zero indicates that we should drop ownership when we have it.
|
||||
upgradeBidPriority(_entity->getSimulationPriority());
|
||||
// because: a _bidPriority of zero indicates that we should drop ownership in the send.
|
||||
// TODO: need to be able to detect when logic dictates we *decrease* priority
|
||||
// WIP: print info whenever _bidPriority mismatches what is known to the entity
|
||||
|
||||
if (_entity->dynamicDataNeedsTransmit()) {
|
||||
uint8_t priority = _entity->hasActions() ? SCRIPT_GRAB_SIMULATION_PRIORITY : SCRIPT_POKE_SIMULATION_PRIORITY;
|
||||
computeNewBidPriority(priority);
|
||||
return true;
|
||||
}
|
||||
computeNewBidPriority(_entity->getSimulationPriority());
|
||||
|
||||
bool parentTransformSuccess;
|
||||
Transform localToWorld = _entity->getParentTransform(parentTransformSuccess);
|
||||
Transform worldToLocal;
|
||||
Transform worldVelocityToLocal;
|
||||
if (parentTransformSuccess) {
|
||||
localToWorld.evalInverse(worldToLocal);
|
||||
worldVelocityToLocal = worldToLocal;
|
||||
worldVelocityToLocal.setTranslation(glm::vec3(0.0f));
|
||||
}
|
||||
|
||||
int numSteps = simulationStep - _lastStep;
|
||||
|
@ -389,12 +397,6 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
|||
}
|
||||
}
|
||||
|
||||
if (_entity->dynamicDataNeedsTransmit()) {
|
||||
uint8_t priority = _entity->hasActions() ? SCRIPT_GRAB_SIMULATION_PRIORITY : SCRIPT_POKE_SIMULATION_PRIORITY;
|
||||
upgradeBidPriority(priority);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Else we measure the error between current and extrapolated transform (according to expected behavior
|
||||
// of remote EntitySimulation) and return true if the error is significant.
|
||||
|
||||
|
@ -439,6 +441,7 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
|||
}
|
||||
|
||||
bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep) {
|
||||
// NOTE: this method is only ever called when the entity simulation is locally owned
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, "ShouldSend");
|
||||
// NOTE: we expect _entity and _body to be valid in this context, since shouldSendUpdate() is only called
|
||||
// after doesNotNeedToSendUpdate() returns false and that call should return 'true' if _entity or _body are NULL.
|
||||
|
@ -447,7 +450,7 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep) {
|
|||
// this case is prevented by setting _ownershipState to UNOWNABLE in EntityMotionState::ctor
|
||||
assert(!(_entity->getClientOnly() && _entity->getOwningAvatarID() != Physics::getSessionUUID()));
|
||||
|
||||
if (_entity->dynamicDataNeedsTransmit() || _entity->queryAACubeNeedsUpdate()) {
|
||||
if (_entity->dynamicDataNeedsTransmit() || (!_entity->getDynamic() && _entity->queryAACubeNeedsUpdate())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -548,10 +551,10 @@ void EntityMotionState::sendBid(OctreeEditPacketSender* packetSender, uint32_t s
|
|||
_lastStep = step;
|
||||
_nextBidExpiry = now + USECS_BETWEEN_OWNERSHIP_BIDS;
|
||||
|
||||
// finally: clear _bidPriority
|
||||
// which will may get promoted before next bid
|
||||
// or maybe we'll win simulation ownership
|
||||
_bidPriority = 0;
|
||||
// after sending the bid we try to clear _bidPriority
|
||||
// which might get promoted again next frame (after local script or simulation interaction)
|
||||
// or we might win the bid
|
||||
computeNewBidPriority(0);
|
||||
}
|
||||
|
||||
void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_t step) {
|
||||
|
@ -686,7 +689,7 @@ uint8_t EntityMotionState::getSimulationPriority() const {
|
|||
}
|
||||
|
||||
void EntityMotionState::slaveBidPriority() {
|
||||
upgradeBidPriority(_entity->getSimulationPriority());
|
||||
computeNewBidPriority(_entity->getSimulationPriority());
|
||||
}
|
||||
|
||||
// virtual
|
||||
|
@ -697,7 +700,7 @@ QUuid EntityMotionState::getSimulatorID() const {
|
|||
|
||||
void EntityMotionState::bump(uint8_t priority) {
|
||||
assert(priority != 0);
|
||||
upgradeBidPriority(glm::max(VOLUNTEER_SIMULATION_PRIORITY, --priority));
|
||||
computeNewBidPriority(glm::max(VOLUNTEER_SIMULATION_PRIORITY, --priority));
|
||||
}
|
||||
|
||||
void EntityMotionState::resetMeasuredBodyAcceleration() {
|
||||
|
@ -776,11 +779,12 @@ void EntityMotionState::computeCollisionGroupAndMask(int16_t& group, int16_t& ma
|
|||
}
|
||||
|
||||
bool EntityMotionState::shouldSendBid() {
|
||||
if (_bidPriority >= glm::max(_entity->getSimulationPriority(), VOLUNTEER_SIMULATION_PRIORITY)) {
|
||||
// NOTE: this method is only ever called when the entity simulation is NOT locally owned
|
||||
if (_bidPriority > glm::max(_entity->getSimulationPriority(), YIELD_SIMULATION_PRIORITY)) {
|
||||
return true;
|
||||
} else {
|
||||
// NOTE: this 'else' case has a side-effect: it clears _bidPriority
|
||||
// which may be updated next simulation step (via collision or script event)
|
||||
// which might get promoted again next frame (after local script or simulation interaction)
|
||||
_bidPriority = 0;
|
||||
return false;
|
||||
}
|
||||
|
@ -791,10 +795,19 @@ bool EntityMotionState::isLocallyOwned() const {
|
|||
}
|
||||
|
||||
bool EntityMotionState::isLocallyOwnedOrShouldBe() const {
|
||||
return (_bidPriority > VOLUNTEER_SIMULATION_PRIORITY && _bidPriority > _entity->getSimulationPriority()) ||
|
||||
// this method could also be called "shouldGenerateCollisionEventForLocalScripts()"
|
||||
// because that is the only reason it's used
|
||||
return (_bidPriority > VOLUNTEER_SIMULATION_PRIORITY && _bidPriority >= _entity->getSimulationPriority()) ||
|
||||
_entity->getSimulatorID() == Physics::getSessionUUID();
|
||||
}
|
||||
|
||||
void EntityMotionState::setRegion(uint8_t region) {
|
||||
_region = region;
|
||||
if (_region == workload::Region::R1 && _bidPriority < VOLUNTEER_SIMULATION_PRIORITY && !isLocallyOwned()) {
|
||||
_bidPriority = VOLUNTEER_SIMULATION_PRIORITY;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityMotionState::initForBid() {
|
||||
assert(_ownershipState != EntityMotionState::OwnershipState::Unownable);
|
||||
_ownershipState = EntityMotionState::OwnershipState::PendingBid;
|
||||
|
@ -805,8 +818,12 @@ void EntityMotionState::initForOwned() {
|
|||
_ownershipState = EntityMotionState::OwnershipState::LocallyOwned;
|
||||
}
|
||||
|
||||
void EntityMotionState::upgradeBidPriority(uint8_t priority) {
|
||||
_bidPriority = glm::max<uint8_t>(_bidPriority, priority);
|
||||
void EntityMotionState::computeNewBidPriority(uint8_t newPriority) {
|
||||
if (_region == workload::Region::R1) {
|
||||
_bidPriority = glm::max<uint8_t>(VOLUNTEER_SIMULATION_PRIORITY, glm::max<uint8_t>(_bidPriority, newPriority));
|
||||
} else {
|
||||
_bidPriority = glm::min<uint8_t>(YIELD_SIMULATION_PRIORITY, newPriority);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityMotionState::clearObjectVelocities() const {
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include <EntityTypes.h>
|
||||
#include <AACube.h>
|
||||
#include <workload/Region.h>
|
||||
|
||||
#include "ObjectMotionState.h"
|
||||
|
||||
|
@ -93,6 +94,8 @@ public:
|
|||
friend class PhysicalEntitySimulation;
|
||||
OwnershipState getOwnershipState() const { return _ownershipState; }
|
||||
|
||||
void setRegion(uint8_t region);
|
||||
|
||||
protected:
|
||||
void updateSendVelocities();
|
||||
uint64_t getNextBidExpiry() const { return _nextBidExpiry; }
|
||||
|
@ -102,11 +105,10 @@ protected:
|
|||
void updateServerPhysicsVariables();
|
||||
bool remoteSimulationOutOfSync(uint32_t simulationStep);
|
||||
|
||||
// changes _bidPriority only if priority is larger
|
||||
void upgradeBidPriority(uint8_t priority);
|
||||
// computes _bidPriority using newPriority and special case rules
|
||||
void computeNewBidPriority(uint8_t newPriority);
|
||||
|
||||
// upgradeBidPriority to value stored in _entity
|
||||
void slaveBidPriority();
|
||||
void slaveBidPriority(); // computeNewBidPriority() with value stored in _entity
|
||||
|
||||
void clearObjectVelocities() const;
|
||||
|
||||
|
@ -155,6 +157,7 @@ protected:
|
|||
mutable uint8_t _accelerationNearlyGravityCount;
|
||||
uint8_t _numInactiveUpdates { 1 };
|
||||
uint8_t _bidPriority { 0 };
|
||||
uint8_t _region { workload::Region::INVALID };
|
||||
bool _serverVariablesSet { false };
|
||||
};
|
||||
|
||||
|
|
|
@ -53,7 +53,9 @@ void PhysicalEntitySimulation::addEntityInternal(EntityItemPointer entity) {
|
|||
bool canBeKinematic = region <= workload::Region::R3;
|
||||
if (shouldBePhysical) {
|
||||
EntityMotionState* motionState = static_cast<EntityMotionState*>(entity->getPhysicsInfo());
|
||||
if (!motionState) {
|
||||
if (motionState) {
|
||||
motionState->setRegion(region);
|
||||
} else {
|
||||
_entitiesToAddToPhysics.insert(entity);
|
||||
}
|
||||
} else if (canBeKinematic && entity->isMovingRelativeToParent()) {
|
||||
|
@ -139,6 +141,7 @@ void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) {
|
|||
} else {
|
||||
_incomingChanges.insert(motionState);
|
||||
}
|
||||
motionState->setRegion(region);
|
||||
} else if (shouldBePhysical) {
|
||||
// The intent is for this object to be in the PhysicsEngine, but it has no MotionState yet.
|
||||
// Perhaps it's shape has changed and it can now be added?
|
||||
|
|
Loading…
Reference in a new issue