mirror of
https://github.com/lubosz/overte.git
synced 2025-04-24 11:43:16 +02:00
always update physics properties when they change
and move activation check logic to MotionState
This commit is contained in:
parent
5135c9dded
commit
e26081e981
7 changed files with 95 additions and 81 deletions
|
@ -35,4 +35,4 @@ namespace AudioConstants {
|
|||
}
|
||||
|
||||
|
||||
#endif // hifi_AudioConstants_h
|
||||
#endif // hifi_AudioConstants_h
|
||||
|
|
|
@ -622,7 +622,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
const QUuid& myNodeID = nodeList->getSessionUUID();
|
||||
bool weOwnSimulation = _simulationOwner.matchesValidID(myNodeID);
|
||||
|
||||
|
||||
|
||||
if (args.bitstreamVersion >= VERSION_ENTITIES_HAVE_SIMULATION_OWNER_AND_ACTIONS_OVER_WIRE) {
|
||||
// pack SimulationOwner and terse update properties near each other
|
||||
|
@ -799,17 +799,11 @@ void EntityItem::setDensity(float density) {
|
|||
_density = glm::max(glm::min(density, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY);
|
||||
}
|
||||
|
||||
const float ACTIVATION_RELATIVE_DENSITY_DELTA = 0.01f; // 1 percent
|
||||
|
||||
void EntityItem::updateDensity(float density) {
|
||||
float clampedDensity = glm::max(glm::min(density, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY);
|
||||
if (_density != clampedDensity) {
|
||||
_density = clampedDensity;
|
||||
|
||||
if (fabsf(_density - clampedDensity) / _density > ACTIVATION_RELATIVE_DENSITY_DELTA) {
|
||||
// the density has changed enough that we should update the physics simulation
|
||||
_dirtyFlags |= Simulation::DIRTY_MASS;
|
||||
}
|
||||
_dirtyFlags |= Simulation::DIRTY_MASS;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -822,11 +816,16 @@ void EntityItem::setMass(float mass) {
|
|||
|
||||
// compute new density
|
||||
const float MIN_VOLUME = 1.0e-6f; // 0.001mm^3
|
||||
float newDensity = 1.0f;
|
||||
if (volume < 1.0e-6f) {
|
||||
// avoid divide by zero
|
||||
_density = glm::min(mass / MIN_VOLUME, ENTITY_ITEM_MAX_DENSITY);
|
||||
newDensity = glm::min(mass / MIN_VOLUME, ENTITY_ITEM_MAX_DENSITY);
|
||||
} else {
|
||||
_density = glm::max(glm::min(mass / volume, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY);
|
||||
newDensity = glm::max(glm::min(mass / volume, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY);
|
||||
}
|
||||
if (_density != newDensity) {
|
||||
_density = newDensity;
|
||||
_dirtyFlags |= Simulation::DIRTY_MASS;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -884,12 +883,12 @@ void EntityItem::simulateKinematicMotion(float timeElapsed, bool setFlags) {
|
|||
#ifdef WANT_DEBUG
|
||||
qCDebug(entities) << "EntityItem::simulateKinematicMotion timeElapsed" << timeElapsed;
|
||||
#endif
|
||||
|
||||
|
||||
const float MIN_TIME_SKIP = 0.0f;
|
||||
const float MAX_TIME_SKIP = 1.0f; // in seconds
|
||||
|
||||
|
||||
timeElapsed = glm::clamp(timeElapsed, MIN_TIME_SKIP, MAX_TIME_SKIP);
|
||||
|
||||
|
||||
if (hasActions()) {
|
||||
return;
|
||||
}
|
||||
|
@ -1312,24 +1311,16 @@ void EntityItem::updatePosition(const glm::vec3& value) {
|
|||
if (shouldSuppressLocationEdits()) {
|
||||
return;
|
||||
}
|
||||
auto delta = glm::distance(getPosition(), value);
|
||||
if (delta > IGNORE_POSITION_DELTA) {
|
||||
_dirtyFlags |= Simulation::DIRTY_POSITION;
|
||||
if (getPosition() != value) {
|
||||
setPosition(value);
|
||||
if (delta > ACTIVATION_POSITION_DELTA) {
|
||||
_dirtyFlags |= Simulation::DIRTY_PHYSICS_ACTIVATION;
|
||||
}
|
||||
_dirtyFlags |= Simulation::DIRTY_POSITION;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateDimensions(const glm::vec3& value) {
|
||||
auto delta = glm::distance(getDimensions(), value);
|
||||
if (delta > IGNORE_DIMENSIONS_DELTA) {
|
||||
if (getDimensions() != value) {
|
||||
setDimensions(value);
|
||||
if (delta > ACTIVATION_DIMENSIONS_DELTA) {
|
||||
// rebuilding the shape will always activate
|
||||
_dirtyFlags |= (Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS);
|
||||
}
|
||||
_dirtyFlags |= (Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1339,14 +1330,7 @@ void EntityItem::updateRotation(const glm::quat& rotation) {
|
|||
}
|
||||
if (getRotation() != rotation) {
|
||||
setRotation(rotation);
|
||||
|
||||
auto alignmentDot = glm::abs(glm::dot(getRotation(), rotation));
|
||||
if (alignmentDot < IGNORE_ALIGNMENT_DOT) {
|
||||
_dirtyFlags |= Simulation::DIRTY_ROTATION;
|
||||
}
|
||||
if (alignmentDot < ACTIVATION_ALIGNMENT_DOT) {
|
||||
_dirtyFlags |= Simulation::DIRTY_PHYSICS_ACTIVATION;
|
||||
}
|
||||
_dirtyFlags |= Simulation::DIRTY_ROTATION;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1367,11 +1351,8 @@ void EntityItem::updateMass(float mass) {
|
|||
newDensity = glm::max(glm::min(mass / volume, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY);
|
||||
}
|
||||
|
||||
float oldDensity = _density;
|
||||
_density = newDensity;
|
||||
|
||||
if (fabsf(_density - oldDensity) / _density > ACTIVATION_RELATIVE_DENSITY_DELTA) {
|
||||
// the density has changed enough that we should update the physics simulation
|
||||
if (_density != newDensity) {
|
||||
_density = newDensity;
|
||||
_dirtyFlags |= Simulation::DIRTY_MASS;
|
||||
}
|
||||
}
|
||||
|
@ -1380,38 +1361,29 @@ void EntityItem::updateVelocity(const glm::vec3& value) {
|
|||
if (shouldSuppressLocationEdits()) {
|
||||
return;
|
||||
}
|
||||
auto delta = glm::distance(_velocity, value);
|
||||
if (delta > IGNORE_LINEAR_VELOCITY_DELTA) {
|
||||
_dirtyFlags |= Simulation::DIRTY_LINEAR_VELOCITY;
|
||||
if (_velocity != value) {
|
||||
const float MIN_LINEAR_SPEED = 0.001f;
|
||||
if (glm::length(value) < MIN_LINEAR_SPEED) {
|
||||
_velocity = ENTITY_ITEM_ZERO_VEC3;
|
||||
} else {
|
||||
_velocity = value;
|
||||
// only activate when setting non-zero velocity
|
||||
if (delta > ACTIVATION_LINEAR_VELOCITY_DELTA) {
|
||||
_dirtyFlags |= Simulation::DIRTY_PHYSICS_ACTIVATION;
|
||||
}
|
||||
}
|
||||
_dirtyFlags |= Simulation::DIRTY_LINEAR_VELOCITY;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateDamping(float value) {
|
||||
auto clampedDamping = glm::clamp(value, 0.0f, 1.0f);
|
||||
if (fabsf(_damping - clampedDamping) > IGNORE_DAMPING_DELTA) {
|
||||
if (_damping != clampedDamping) {
|
||||
_damping = clampedDamping;
|
||||
_dirtyFlags |= Simulation::DIRTY_MATERIAL;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateGravity(const glm::vec3& value) {
|
||||
auto delta = glm::distance(_gravity, value);
|
||||
if (delta > IGNORE_GRAVITY_DELTA) {
|
||||
if (_gravity != value) {
|
||||
_gravity = value;
|
||||
_dirtyFlags |= Simulation::DIRTY_LINEAR_VELOCITY;
|
||||
if (delta > ACTIVATION_GRAVITY_DELTA) {
|
||||
_dirtyFlags |= Simulation::DIRTY_PHYSICS_ACTIVATION;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1419,25 +1391,20 @@ void EntityItem::updateAngularVelocity(const glm::vec3& value) {
|
|||
if (shouldSuppressLocationEdits()) {
|
||||
return;
|
||||
}
|
||||
auto delta = glm::distance(_angularVelocity, value);
|
||||
if (delta > IGNORE_ANGULAR_VELOCITY_DELTA) {
|
||||
_dirtyFlags |= Simulation::DIRTY_ANGULAR_VELOCITY;
|
||||
if (_angularVelocity != value) {
|
||||
const float MIN_ANGULAR_SPEED = 0.0002f;
|
||||
if (glm::length(value) < MIN_ANGULAR_SPEED) {
|
||||
_angularVelocity = ENTITY_ITEM_ZERO_VEC3;
|
||||
} else {
|
||||
_angularVelocity = value;
|
||||
// only activate when setting non-zero velocity
|
||||
if (delta > ACTIVATION_ANGULAR_VELOCITY_DELTA) {
|
||||
_dirtyFlags |= Simulation::DIRTY_PHYSICS_ACTIVATION;
|
||||
}
|
||||
}
|
||||
_dirtyFlags |= Simulation::DIRTY_ANGULAR_VELOCITY;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateAngularDamping(float value) {
|
||||
auto clampedDamping = glm::clamp(value, 0.0f, 1.0f);
|
||||
if (fabsf(_angularDamping - clampedDamping) > IGNORE_DAMPING_DELTA) {
|
||||
if (_angularDamping != clampedDamping) {
|
||||
_angularDamping = clampedDamping;
|
||||
_dirtyFlags |= Simulation::DIRTY_MATERIAL;
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ namespace render {
|
|||
class PendingChanges;
|
||||
}
|
||||
|
||||
/*
|
||||
// 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;
|
||||
|
@ -64,6 +65,7 @@ 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 ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() { };
|
||||
|
|
|
@ -95,7 +95,7 @@ void EntityMotionState::updateServerPhysicsVariables(const QUuid& sessionID) {
|
|||
}
|
||||
|
||||
// virtual
|
||||
bool EntityMotionState::handleEasyChanges(uint32_t flags, PhysicsEngine* engine) {
|
||||
bool EntityMotionState::handleEasyChanges(uint32_t& flags, PhysicsEngine* engine) {
|
||||
assert(entityTreeIsLocked());
|
||||
updateServerPhysicsVariables(engine->getSessionID());
|
||||
ObjectMotionState::handleEasyChanges(flags, engine);
|
||||
|
@ -120,7 +120,7 @@ bool EntityMotionState::handleEasyChanges(uint32_t flags, PhysicsEngine* engine)
|
|||
}
|
||||
if (flags & Simulation::DIRTY_SIMULATOR_OWNERSHIP) {
|
||||
// (DIRTY_SIMULATOR_OWNERSHIP really means "we should bid for ownership with SCRIPT priority")
|
||||
// we're manipulating this object directly via script, so we artificially
|
||||
// we're manipulating this object directly via script, so we artificially
|
||||
// manipulate the logic to trigger an immediate bid for ownership
|
||||
setOutgoingPriority(SCRIPT_EDIT_SIMULATION_PRIORITY);
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ bool EntityMotionState::handleEasyChanges(uint32_t flags, PhysicsEngine* engine)
|
|||
|
||||
|
||||
// virtual
|
||||
bool EntityMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine) {
|
||||
bool EntityMotionState::handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine) {
|
||||
updateServerPhysicsVariables(engine->getSessionID());
|
||||
return ObjectMotionState::handleHardAndEasyChanges(flags, engine);
|
||||
}
|
||||
|
|
|
@ -29,8 +29,8 @@ public:
|
|||
virtual ~EntityMotionState();
|
||||
|
||||
void updateServerPhysicsVariables(const QUuid& sessionID);
|
||||
virtual bool handleEasyChanges(uint32_t flags, PhysicsEngine* engine);
|
||||
virtual bool 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;
|
||||
|
|
|
@ -17,6 +17,14 @@
|
|||
#include "PhysicsHelpers.h"
|
||||
#include "PhysicsLogging.h"
|
||||
|
||||
// these thresholds determine what updates (object-->body) will activate the physical object
|
||||
const float ACTIVATION_POSITION_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;
|
||||
|
||||
|
||||
// origin of physics simulation in world-frame
|
||||
glm::vec3 _worldOffset(0.0f);
|
||||
|
||||
|
@ -128,28 +136,65 @@ void ObjectMotionState::setRigidBody(btRigidBody* body) {
|
|||
}
|
||||
}
|
||||
|
||||
bool ObjectMotionState::handleEasyChanges(uint32_t flags, PhysicsEngine* engine) {
|
||||
bool ObjectMotionState::handleEasyChanges(uint32_t& flags, PhysicsEngine* engine) {
|
||||
if (flags & Simulation::DIRTY_POSITION) {
|
||||
btTransform worldTrans;
|
||||
if (flags & Simulation::DIRTY_ROTATION) {
|
||||
worldTrans.setRotation(glmToBullet(getObjectRotation()));
|
||||
} else {
|
||||
worldTrans = _body->getWorldTransform();
|
||||
btTransform worldTrans = _body->getWorldTransform();
|
||||
btVector3 newPosition = glmToBullet(getObjectPosition());
|
||||
float delta = (newPosition - worldTrans.getOrigin()).length();
|
||||
if (delta > ACTIVATION_POSITION_DELTA) {
|
||||
flags |= Simulation::DIRTY_PHYSICS_ACTIVATION;
|
||||
}
|
||||
worldTrans.setOrigin(newPosition);
|
||||
|
||||
if (flags & Simulation::DIRTY_ROTATION) {
|
||||
btQuaternion newRotation = glmToBullet(getObjectRotation());
|
||||
float alignmentDot = fabsf(worldTrans.getRotation().dot(newRotation));
|
||||
if (alignmentDot < ACTIVATION_ALIGNMENT_DOT) {
|
||||
flags |= Simulation::DIRTY_PHYSICS_ACTIVATION;
|
||||
}
|
||||
worldTrans.setRotation(newRotation);
|
||||
}
|
||||
worldTrans.setOrigin(glmToBullet(getObjectPosition()));
|
||||
_body->setWorldTransform(worldTrans);
|
||||
} else if (flags & Simulation::DIRTY_ROTATION) {
|
||||
btTransform worldTrans = _body->getWorldTransform();
|
||||
worldTrans.setRotation(glmToBullet(getObjectRotation()));
|
||||
btQuaternion newRotation = glmToBullet(getObjectRotation());
|
||||
float alignmentDot = fabsf(worldTrans.getRotation().dot(newRotation));
|
||||
if (alignmentDot < ACTIVATION_ALIGNMENT_DOT) {
|
||||
flags |= Simulation::DIRTY_PHYSICS_ACTIVATION;
|
||||
}
|
||||
worldTrans.setRotation(newRotation);
|
||||
_body->setWorldTransform(worldTrans);
|
||||
}
|
||||
|
||||
if (flags & Simulation::DIRTY_LINEAR_VELOCITY) {
|
||||
_body->setLinearVelocity(glmToBullet(getObjectLinearVelocity()));
|
||||
_body->setGravity(glmToBullet(getObjectGravity()));
|
||||
btVector3 newLinearVelocity = glmToBullet(getObjectLinearVelocity());
|
||||
if (!(flags & Simulation::DIRTY_PHYSICS_ACTIVATION)) {
|
||||
float delta = (newLinearVelocity - _body->getLinearVelocity()).length();
|
||||
if (delta > ACTIVATION_LINEAR_VELOCITY_DELTA) {
|
||||
flags |= Simulation::DIRTY_PHYSICS_ACTIVATION;
|
||||
}
|
||||
}
|
||||
_body->setLinearVelocity(newLinearVelocity);
|
||||
|
||||
btVector3 newGravity = glmToBullet(getObjectGravity());
|
||||
if (!(flags & Simulation::DIRTY_PHYSICS_ACTIVATION)) {
|
||||
float delta = (newGravity - _body->getGravity()).length();
|
||||
if (delta > ACTIVATION_GRAVITY_DELTA ||
|
||||
(delta > 0.0f && _body->getGravity().length2() == 0.0f)) {
|
||||
flags |= Simulation::DIRTY_PHYSICS_ACTIVATION;
|
||||
}
|
||||
}
|
||||
_body->setGravity(newGravity);
|
||||
}
|
||||
if (flags & Simulation::DIRTY_ANGULAR_VELOCITY) {
|
||||
_body->setAngularVelocity(glmToBullet(getObjectAngularVelocity()));
|
||||
btVector3 newAngularVelocity = glmToBullet(getObjectAngularVelocity());
|
||||
if (!(flags & Simulation::DIRTY_PHYSICS_ACTIVATION)) {
|
||||
float delta = (newAngularVelocity - _body->getAngularVelocity()).length();
|
||||
if (delta > ACTIVATION_ANGULAR_VELOCITY_DELTA) {
|
||||
flags |= Simulation::DIRTY_PHYSICS_ACTIVATION;
|
||||
}
|
||||
}
|
||||
_body->setAngularVelocity(newAngularVelocity);
|
||||
}
|
||||
|
||||
if (flags & Simulation::DIRTY_MATERIAL) {
|
||||
|
@ -163,7 +208,7 @@ bool ObjectMotionState::handleEasyChanges(uint32_t flags, PhysicsEngine* engine)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ObjectMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine) {
|
||||
bool ObjectMotionState::handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine) {
|
||||
if (flags & Simulation::DIRTY_SHAPE) {
|
||||
// make sure the new shape is valid
|
||||
if (!isReadyToComputeShape()) {
|
||||
|
@ -195,8 +240,8 @@ bool ObjectMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine*
|
|||
if (flags & EASY_DIRTY_PHYSICS_FLAGS) {
|
||||
handleEasyChanges(flags, engine);
|
||||
}
|
||||
// it is possible that there are no HARD flags at this point (if DIRTY_SHAPE was removed)
|
||||
// so we check again befoe we reinsert:
|
||||
// it is possible there are no HARD flags at this point (if DIRTY_SHAPE was removed)
|
||||
// so we check again before we reinsert:
|
||||
if (flags & HARD_DIRTY_PHYSICS_FLAGS) {
|
||||
engine->reinsertObject(this);
|
||||
}
|
||||
|
|
|
@ -80,8 +80,8 @@ public:
|
|||
ObjectMotionState(btCollisionShape* shape);
|
||||
~ObjectMotionState();
|
||||
|
||||
virtual bool handleEasyChanges(uint32_t flags, PhysicsEngine* engine);
|
||||
virtual bool 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();
|
||||
|
|
Loading…
Reference in a new issue