Merge pull request #4794 from AndrewMeadows/nova

fix crash when script deletes entity
This commit is contained in:
Seth Alves 2015-05-07 16:12:14 -07:00
commit 70cfd5a2a5
6 changed files with 85 additions and 98 deletions

View file

@ -1105,23 +1105,6 @@ void EntityItem::computeShapeInfo(ShapeInfo& info) {
info.setParams(getShapeType(), 0.5f * getDimensions()); info.setParams(getShapeType(), 0.5f * getDimensions());
} }
// these thesholds determine what updates will be ignored (client and server)
const float IGNORE_POSITION_DELTA = 0.0001f;
const float IGNORE_DIMENSIONS_DELTA = 0.0005f;
const float IGNORE_ALIGNMENT_DOT = 0.99997f;
const float IGNORE_LINEAR_VELOCITY_DELTA = 0.001f;
const float IGNORE_DAMPING_DELTA = 0.001f;
const float IGNORE_GRAVITY_DELTA = 0.001f;
const float IGNORE_ANGULAR_VELOCITY_DELTA = 0.0002f;
// these thresholds determine what updates will activate the physical object
const float ACTIVATION_POSITION_DELTA = 0.005f;
const float ACTIVATION_DIMENSIONS_DELTA = 0.005f;
const float ACTIVATION_ALIGNMENT_DOT = 0.99990f;
const float ACTIVATION_LINEAR_VELOCITY_DELTA = 0.01f;
const float ACTIVATION_GRAVITY_DELTA = 0.1f;
const float ACTIVATION_ANGULAR_VELOCITY_DELTA = 0.03f;
void EntityItem::updatePositionInDomainUnits(const glm::vec3& value) { void EntityItem::updatePositionInDomainUnits(const glm::vec3& value) {
glm::vec3 position = value * (float)TREE_SCALE; glm::vec3 position = value * (float)TREE_SCALE;
updatePosition(position); updatePosition(position);

View file

@ -32,6 +32,24 @@ class EntitySimulation;
class EntityTreeElement; class EntityTreeElement;
class EntityTreeElementExtraEncodeData; class EntityTreeElementExtraEncodeData;
// these thesholds determine what updates will be ignored (client and server)
const float IGNORE_POSITION_DELTA = 0.0001f;
const float IGNORE_DIMENSIONS_DELTA = 0.0005f;
const float IGNORE_ALIGNMENT_DOT = 0.99997f;
const float IGNORE_LINEAR_VELOCITY_DELTA = 0.001f;
const float IGNORE_DAMPING_DELTA = 0.001f;
const float IGNORE_GRAVITY_DELTA = 0.001f;
const float IGNORE_ANGULAR_VELOCITY_DELTA = 0.0002f;
// these thresholds determine what updates will activate the physical object
const float ACTIVATION_POSITION_DELTA = 0.005f;
const float ACTIVATION_DIMENSIONS_DELTA = 0.005f;
const float ACTIVATION_ALIGNMENT_DOT = 0.99990f;
const float ACTIVATION_LINEAR_VELOCITY_DELTA = 0.01f;
const float ACTIVATION_GRAVITY_DELTA = 0.1f;
const float ACTIVATION_ANGULAR_VELOCITY_DELTA = 0.03f;
#define DONT_ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() = 0; #define DONT_ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() = 0;
#define ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() { }; #define ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() { };
@ -395,14 +413,4 @@ protected:
bool _simulated; // set by EntitySimulation bool _simulated; // set by EntitySimulation
}; };
extern const float IGNORE_POSITION_DELTA;
extern const float IGNORE_DIMENSIONS_DELTA;
extern const float IGNORE_ALIGNMENT_DOT;
extern const float IGNORE_LINEAR_VELOCITY_DELTA;
extern const float IGNORE_DAMPING_DELTA;
extern const float IGNORE_GRAVITY_DELTA;
extern const float IGNORE_ANGULAR_VELOCITY_DELTA;
#endif // hifi_EntityItem_h #endif // hifi_EntityItem_h

View file

@ -12,6 +12,7 @@
#ifndef hifi_EntityTree_h #ifndef hifi_EntityTree_h
#define hifi_EntityTree_h #define hifi_EntityTree_h
#include <QSet>
#include <QVector> #include <QVector>
#include <Octree.h> #include <Octree.h>

View file

@ -27,13 +27,13 @@ EntityMotionState::EntityMotionState(btCollisionShape* shape, EntityItem* entity
_entity(entity), _entity(entity),
_sentMoving(false), _sentMoving(false),
_numNonMovingUpdates(0), _numNonMovingUpdates(0),
_sentStep(0), _lastStep(0),
_sentPosition(0.0f), _serverPosition(0.0f),
_sentRotation(), _serverRotation(),
_sentVelocity(0.0f), _serverVelocity(0.0f),
_sentAngularVelocity(0.0f), _serverAngularVelocity(0.0f),
_sentGravity(0.0f), _serverGravity(0.0f),
_sentAcceleration(0.0f), _serverAcceleration(0.0f),
_accelerationNearlyGravityCount(0), _accelerationNearlyGravityCount(0),
_shouldClaimSimulationOwnership(false), _shouldClaimSimulationOwnership(false),
_movingStepsWithoutSimulationOwner(0) _movingStepsWithoutSimulationOwner(0)
@ -49,16 +49,16 @@ EntityMotionState::~EntityMotionState() {
void EntityMotionState::updateServerPhysicsVariables(uint32_t flags) { void EntityMotionState::updateServerPhysicsVariables(uint32_t flags) {
if (flags & EntityItem::DIRTY_POSITION) { if (flags & EntityItem::DIRTY_POSITION) {
_sentPosition = _entity->getPosition(); _serverPosition = _entity->getPosition();
} }
if (flags & EntityItem::DIRTY_ROTATION) { if (flags & EntityItem::DIRTY_ROTATION) {
_sentRotation = _entity->getRotation(); _serverRotation = _entity->getRotation();
} }
if (flags & EntityItem::DIRTY_LINEAR_VELOCITY) { if (flags & EntityItem::DIRTY_LINEAR_VELOCITY) {
_sentVelocity = _entity->getVelocity(); _serverVelocity = _entity->getVelocity();
} }
if (flags & EntityItem::DIRTY_ANGULAR_VELOCITY) { if (flags & EntityItem::DIRTY_ANGULAR_VELOCITY) {
_sentAngularVelocity = _entity->getAngularVelocity(); _serverAngularVelocity = _entity->getAngularVelocity();
} }
} }
@ -96,8 +96,8 @@ bool EntityMotionState::isMoving() const {
} }
bool EntityMotionState::isMovingVsServer() const { bool EntityMotionState::isMovingVsServer() const {
auto alignmentDot = glm::abs(glm::dot(_sentRotation, _entity->getRotation())); auto alignmentDot = glm::abs(glm::dot(_serverRotation, _entity->getRotation()));
if (glm::distance(_sentPosition, _entity->getPosition()) > IGNORE_POSITION_DELTA || if (glm::distance(_serverPosition, _entity->getPosition()) > IGNORE_POSITION_DELTA ||
alignmentDot < IGNORE_ALIGNMENT_DOT) { alignmentDot < IGNORE_ALIGNMENT_DOT) {
return true; return true;
} }
@ -183,26 +183,26 @@ bool EntityMotionState::doesNotNeedToSendUpdate() const {
bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) { bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
assert(_body); assert(_body);
// if we've never checked before, our _sentStep will be 0, and we need to initialize our state // if we've never checked before, our _lastStep will be 0, and we need to initialize our state
if (_sentStep == 0) { if (_lastStep == 0) {
btTransform xform = _body->getWorldTransform(); btTransform xform = _body->getWorldTransform();
_sentPosition = bulletToGLM(xform.getOrigin()); _serverPosition = bulletToGLM(xform.getOrigin());
_sentRotation = bulletToGLM(xform.getRotation()); _serverRotation = bulletToGLM(xform.getRotation());
_sentVelocity = bulletToGLM(_body->getLinearVelocity()); _serverVelocity = bulletToGLM(_body->getLinearVelocity());
_sentAngularVelocity = bulletToGLM(_body->getAngularVelocity()); _serverAngularVelocity = bulletToGLM(_body->getAngularVelocity());
_sentStep = simulationStep; _lastStep = simulationStep;
return false; return false;
} }
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
glm::vec3 wasPosition = _sentPosition; glm::vec3 wasPosition = _serverPosition;
glm::quat wasRotation = _sentRotation; glm::quat wasRotation = _serverRotation;
glm::vec3 wasAngularVelocity = _sentAngularVelocity; glm::vec3 wasAngularVelocity = _serverAngularVelocity;
#endif #endif
int numSteps = simulationStep - _sentStep; int numSteps = simulationStep - _lastStep;
float dt = (float)(numSteps) * PHYSICS_ENGINE_FIXED_SUBSTEP; float dt = (float)(numSteps) * PHYSICS_ENGINE_FIXED_SUBSTEP;
_sentStep = simulationStep; _lastStep = simulationStep;
bool isActive = _body->isActive(); bool isActive = _body->isActive();
if (!isActive) { if (!isActive) {
@ -226,16 +226,16 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
// due to _worldOffset. // due to _worldOffset.
// compute position error // compute position error
if (glm::length2(_sentVelocity) > 0.0f) { if (glm::length2(_serverVelocity) > 0.0f) {
_sentVelocity += _sentAcceleration * dt; _serverVelocity += _serverAcceleration * dt;
_sentVelocity *= powf(1.0f - _body->getLinearDamping(), dt); _serverVelocity *= powf(1.0f - _body->getLinearDamping(), dt);
_sentPosition += dt * _sentVelocity; _serverPosition += dt * _serverVelocity;
} }
btTransform worldTrans = _body->getWorldTransform(); btTransform worldTrans = _body->getWorldTransform();
glm::vec3 position = bulletToGLM(worldTrans.getOrigin()); glm::vec3 position = bulletToGLM(worldTrans.getOrigin());
float dx2 = glm::distance2(position, _sentPosition); float dx2 = glm::distance2(position, _serverPosition);
const float MAX_POSITION_ERROR_SQUARED = 0.001f; // 0.001 m^2 ~~> 0.03 m const float MAX_POSITION_ERROR_SQUARED = 0.001f; // 0.001 m^2 ~~> 0.03 m
if (dx2 > MAX_POSITION_ERROR_SQUARED) { if (dx2 > MAX_POSITION_ERROR_SQUARED) {
@ -244,44 +244,44 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
qCDebug(physics) << ".... (dx2 > MAX_POSITION_ERROR_SQUARED) ...."; qCDebug(physics) << ".... (dx2 > MAX_POSITION_ERROR_SQUARED) ....";
qCDebug(physics) << "wasPosition:" << wasPosition; qCDebug(physics) << "wasPosition:" << wasPosition;
qCDebug(physics) << "bullet position:" << position; qCDebug(physics) << "bullet position:" << position;
qCDebug(physics) << "_sentPosition:" << _sentPosition; qCDebug(physics) << "_serverPosition:" << _serverPosition;
qCDebug(physics) << "dx2:" << dx2; qCDebug(physics) << "dx2:" << dx2;
#endif #endif
return true; return true;
} }
if (glm::length2(_sentAngularVelocity) > 0.0f) { if (glm::length2(_serverAngularVelocity) > 0.0f) {
// compute rotation error // compute rotation error
float attenuation = powf(1.0f - _body->getAngularDamping(), dt); float attenuation = powf(1.0f - _body->getAngularDamping(), dt);
_sentAngularVelocity *= attenuation; _serverAngularVelocity *= attenuation;
// Bullet caps the effective rotation velocity inside its rotation integration step, therefore // Bullet caps the effective rotation velocity inside its rotation integration step, therefore
// we must integrate with the same algorithm and timestep in order achieve similar results. // we must integrate with the same algorithm and timestep in order achieve similar results.
for (int i = 0; i < numSteps; ++i) { for (int i = 0; i < numSteps; ++i) {
_sentRotation = glm::normalize(computeBulletRotationStep(_sentAngularVelocity, PHYSICS_ENGINE_FIXED_SUBSTEP) * _sentRotation); _serverRotation = glm::normalize(computeBulletRotationStep(_serverAngularVelocity, PHYSICS_ENGINE_FIXED_SUBSTEP) * _serverRotation);
} }
} }
const float MIN_ROTATION_DOT = 0.99f; // 0.99 dot threshold coresponds to about 16 degrees of slop const float MIN_ROTATION_DOT = 0.99f; // 0.99 dot threshold coresponds to about 16 degrees of slop
glm::quat actualRotation = bulletToGLM(worldTrans.getRotation()); glm::quat actualRotation = bulletToGLM(worldTrans.getRotation());
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
if ((fabsf(glm::dot(actualRotation, _sentRotation)) < MIN_ROTATION_DOT)) { if ((fabsf(glm::dot(actualRotation, _serverRotation)) < MIN_ROTATION_DOT)) {
qCDebug(physics) << ".... ((fabsf(glm::dot(actualRotation, _sentRotation)) < MIN_ROTATION_DOT)) ...."; qCDebug(physics) << ".... ((fabsf(glm::dot(actualRotation, _serverRotation)) < MIN_ROTATION_DOT)) ....";
qCDebug(physics) << "wasAngularVelocity:" << wasAngularVelocity; qCDebug(physics) << "wasAngularVelocity:" << wasAngularVelocity;
qCDebug(physics) << "_sentAngularVelocity:" << _sentAngularVelocity; qCDebug(physics) << "_serverAngularVelocity:" << _serverAngularVelocity;
qCDebug(physics) << "length wasAngularVelocity:" << glm::length(wasAngularVelocity); qCDebug(physics) << "length wasAngularVelocity:" << glm::length(wasAngularVelocity);
qCDebug(physics) << "length _sentAngularVelocity:" << glm::length(_sentAngularVelocity); qCDebug(physics) << "length _serverAngularVelocity:" << glm::length(_serverAngularVelocity);
qCDebug(physics) << "wasRotation:" << wasRotation; qCDebug(physics) << "wasRotation:" << wasRotation;
qCDebug(physics) << "bullet actualRotation:" << actualRotation; qCDebug(physics) << "bullet actualRotation:" << actualRotation;
qCDebug(physics) << "_sentRotation:" << _sentRotation; qCDebug(physics) << "_serverRotation:" << _serverRotation;
} }
#endif #endif
return (fabsf(glm::dot(actualRotation, _sentRotation)) < MIN_ROTATION_DOT); return (fabsf(glm::dot(actualRotation, _serverRotation)) < MIN_ROTATION_DOT);
} }
bool EntityMotionState::shouldSendUpdate(uint32_t simulationFrame) { bool EntityMotionState::shouldSendUpdate(uint32_t simulationFrame) {
@ -335,42 +335,42 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
} }
btTransform worldTrans = _body->getWorldTransform(); btTransform worldTrans = _body->getWorldTransform();
_sentPosition = bulletToGLM(worldTrans.getOrigin()); _serverPosition = bulletToGLM(worldTrans.getOrigin());
properties.setPosition(_sentPosition + ObjectMotionState::getWorldOffset()); properties.setPosition(_serverPosition + ObjectMotionState::getWorldOffset());
_sentRotation = bulletToGLM(worldTrans.getRotation()); _serverRotation = bulletToGLM(worldTrans.getRotation());
properties.setRotation(_sentRotation); properties.setRotation(_serverRotation);
bool zeroSpeed = true; bool zeroSpeed = true;
bool zeroSpin = true; bool zeroSpin = true;
if (_body->isActive()) { if (_body->isActive()) {
_sentVelocity = bulletToGLM(_body->getLinearVelocity()); _serverVelocity = bulletToGLM(_body->getLinearVelocity());
_sentAngularVelocity = bulletToGLM(_body->getAngularVelocity()); _serverAngularVelocity = bulletToGLM(_body->getAngularVelocity());
// if the speeds are very small we zero them out // if the speeds are very small we zero them out
const float MINIMUM_EXTRAPOLATION_SPEED_SQUARED = 1.0e-4f; // 1cm/sec const float MINIMUM_EXTRAPOLATION_SPEED_SQUARED = 1.0e-4f; // 1cm/sec
zeroSpeed = (glm::length2(_sentVelocity) < MINIMUM_EXTRAPOLATION_SPEED_SQUARED); zeroSpeed = (glm::length2(_serverVelocity) < MINIMUM_EXTRAPOLATION_SPEED_SQUARED);
if (zeroSpeed) { if (zeroSpeed) {
_sentVelocity = glm::vec3(0.0f); _serverVelocity = glm::vec3(0.0f);
} }
const float MINIMUM_EXTRAPOLATION_SPIN_SQUARED = 0.004f; // ~0.01 rotation/sec const float MINIMUM_EXTRAPOLATION_SPIN_SQUARED = 0.004f; // ~0.01 rotation/sec
zeroSpin = glm::length2(_sentAngularVelocity) < MINIMUM_EXTRAPOLATION_SPIN_SQUARED; zeroSpin = glm::length2(_serverAngularVelocity) < MINIMUM_EXTRAPOLATION_SPIN_SQUARED;
if (zeroSpin) { if (zeroSpin) {
_sentAngularVelocity = glm::vec3(0.0f); _serverAngularVelocity = glm::vec3(0.0f);
} }
_sentMoving = ! (zeroSpeed && zeroSpin); _sentMoving = ! (zeroSpeed && zeroSpin);
} else { } else {
_sentVelocity = _sentAngularVelocity = glm::vec3(0.0f); _serverVelocity = _serverAngularVelocity = glm::vec3(0.0f);
_sentMoving = false; _sentMoving = false;
} }
properties.setVelocity(_sentVelocity); properties.setVelocity(_serverVelocity);
_sentGravity = _entity->getGravity(); _serverGravity = _entity->getGravity();
properties.setGravity(_entity->getGravity()); properties.setGravity(_entity->getGravity());
_sentAcceleration = _entity->getAcceleration(); _serverAcceleration = _entity->getAcceleration();
properties.setAcceleration(_sentAcceleration); properties.setAcceleration(_serverAcceleration);
properties.setAngularVelocity(_sentAngularVelocity); properties.setAngularVelocity(_serverAngularVelocity);
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
QUuid myNodeID = nodeList->getSessionUUID(); QUuid myNodeID = nodeList->getSessionUUID();
@ -430,7 +430,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
#endif #endif
} }
_sentStep = step; _lastStep = step;
} }
uint32_t EntityMotionState::getAndClearIncomingDirtyFlags() const { uint32_t EntityMotionState::getAndClearIncomingDirtyFlags() const {

View file

@ -95,14 +95,14 @@ protected:
bool _sentMoving; // true if last update was moving bool _sentMoving; // true if last update was moving
int _numNonMovingUpdates; // RELIABLE_SEND_HACK for "not so reliable" resends of packets for non-moving objects int _numNonMovingUpdates; // RELIABLE_SEND_HACK for "not so reliable" resends of packets for non-moving objects
// TODO XXX rename _sent* to _server* // these are for the prediction of the remote server's simple extrapolation
uint32_t _sentStep; uint32_t _lastStep; // last step of server extrapolation
glm::vec3 _sentPosition; // in simulation-frame (not world-frame) glm::vec3 _serverPosition; // in simulation-frame (not world-frame)
glm::quat _sentRotation;; glm::quat _serverRotation;
glm::vec3 _sentVelocity; glm::vec3 _serverVelocity;
glm::vec3 _sentAngularVelocity; // radians per second glm::vec3 _serverAngularVelocity; // radians per second
glm::vec3 _sentGravity; glm::vec3 _serverGravity;
glm::vec3 _sentAcceleration; glm::vec3 _serverAcceleration;
uint32_t _lastMeasureStep; uint32_t _lastMeasureStep;
glm::vec3 _lastVelocity; glm::vec3 _lastVelocity;

View file

@ -62,15 +62,10 @@ void PhysicalEntitySimulation::removeEntityInternal(EntityItem* entity) {
if (motionState) { if (motionState) {
motionState->clearEntity(); motionState->clearEntity();
entity->setPhysicsInfo(nullptr); entity->setPhysicsInfo(nullptr);
// NOTE: we must remove entity from _pendingAdds immediately because we've disconnected the backpointers between
// motionState and entity and they can't be used to look up each other. However we don't need to remove
// motionState from _pendingChanges at this time becuase it will be removed during getObjectsToDelete().
_pendingAdds.remove(entity);
_pendingRemoves.insert(motionState); _pendingRemoves.insert(motionState);
_outgoingChanges.remove(motionState); _outgoingChanges.remove(motionState);
} }
_pendingAdds.remove(entity);
} }
void PhysicalEntitySimulation::changeEntityInternal(EntityItem* entity) { void PhysicalEntitySimulation::changeEntityInternal(EntityItem* entity) {