mirror of
https://github.com/overte-org/overte.git
synced 2025-08-05 01:59:59 +02:00
various physics-related experiments
This commit is contained in:
parent
0daaf20f01
commit
cf0499e671
5 changed files with 141 additions and 59 deletions
|
@ -65,7 +65,13 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) :
|
|||
_marketplaceID(ENTITY_ITEM_DEFAULT_MARKETPLACE_ID),
|
||||
_physicsInfo(NULL),
|
||||
_dirtyFlags(0),
|
||||
_element(NULL)
|
||||
_element(NULL),
|
||||
_previousPositionFromServer(ENTITY_ITEM_ZERO_VEC3),
|
||||
_previousRotationFromServer(ENTITY_ITEM_DEFAULT_ROTATION),
|
||||
_previousVelocityFromServer(ENTITY_ITEM_ZERO_VEC3),
|
||||
_previousAngularVelocityFromServer(ENTITY_ITEM_ZERO_VEC3),
|
||||
_previousGravityFromServer(ENTITY_ITEM_ZERO_VEC3),
|
||||
_previousAccelerationFromServer(ENTITY_ITEM_ZERO_VEC3)
|
||||
{
|
||||
quint64 now = usecTimestampNow();
|
||||
_lastSimulated = now;
|
||||
|
@ -592,7 +598,10 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
#ifdef WANT_DEBUG
|
||||
qCDebug(entities) << "skipTimeForward:" << skipTimeForward;
|
||||
#endif
|
||||
simulateKinematicMotion(skipTimeForward);
|
||||
|
||||
// we want to extrapolate the motion forward to compensate for packet travel time, but
|
||||
// we don't want the side effect of flag setting.
|
||||
simulateKinematicMotion(skipTimeForward, false);
|
||||
}
|
||||
_lastSimulated = now;
|
||||
}
|
||||
|
@ -725,7 +734,7 @@ void EntityItem::simulate(const quint64& now) {
|
|||
_lastSimulated = now;
|
||||
}
|
||||
|
||||
void EntityItem::simulateKinematicMotion(float timeElapsed) {
|
||||
void EntityItem::simulateKinematicMotion(float timeElapsed, bool setFlags) {
|
||||
if (hasAngularVelocity()) {
|
||||
// angular damping
|
||||
if (_angularDamping > 0.0f) {
|
||||
|
@ -740,7 +749,7 @@ void EntityItem::simulateKinematicMotion(float timeElapsed) {
|
|||
|
||||
const float EPSILON_ANGULAR_VELOCITY_LENGTH = 0.0017453f; // 0.0017453 rad/sec = 0.1f degrees/sec
|
||||
if (angularSpeed < EPSILON_ANGULAR_VELOCITY_LENGTH) {
|
||||
if (angularSpeed > 0.0f) {
|
||||
if (setFlags && angularSpeed > 0.0f) {
|
||||
_dirtyFlags |= EntityItem::DIRTY_MOTION_TYPE;
|
||||
}
|
||||
_angularVelocity = ENTITY_ITEM_ZERO_VEC3;
|
||||
|
@ -802,7 +811,7 @@ void EntityItem::simulateKinematicMotion(float timeElapsed) {
|
|||
const float EPSILON_LINEAR_VELOCITY_LENGTH = 0.001f; // 1mm/sec
|
||||
if (speed < EPSILON_LINEAR_VELOCITY_LENGTH) {
|
||||
setVelocity(ENTITY_ITEM_ZERO_VEC3);
|
||||
if (speed > 0.0f) {
|
||||
if (setFlags && speed > 0.0f) {
|
||||
_dirtyFlags |= EntityItem::DIRTY_MOTION_TYPE;
|
||||
}
|
||||
} else {
|
||||
|
@ -1089,8 +1098,11 @@ void EntityItem::updatePositionInDomainUnits(const glm::vec3& value) {
|
|||
}
|
||||
|
||||
void EntityItem::updatePosition(const glm::vec3& value) {
|
||||
if (glm::distance(_position, value) > MIN_POSITION_DELTA) {
|
||||
if (value == _previousPositionFromServer) {
|
||||
_position = value;
|
||||
} else if (glm::distance(_position, value) > MIN_POSITION_DELTA) {
|
||||
_position = value;
|
||||
_previousPositionFromServer = value;
|
||||
_dirtyFlags |= EntityItem::DIRTY_POSITION;
|
||||
}
|
||||
}
|
||||
|
@ -1108,8 +1120,11 @@ void EntityItem::updateDimensions(const glm::vec3& value) {
|
|||
}
|
||||
|
||||
void EntityItem::updateRotation(const glm::quat& rotation) {
|
||||
if (glm::dot(_rotation, rotation) < MIN_ALIGNMENT_DOT) {
|
||||
_rotation = rotation;
|
||||
if (rotation == _previousRotationFromServer) {
|
||||
_rotation = rotation;
|
||||
} else if (glm::abs(glm::dot(_rotation, rotation)) < MIN_ALIGNMENT_DOT) {
|
||||
_rotation = rotation;
|
||||
_previousRotationFromServer = rotation;
|
||||
_dirtyFlags |= EntityItem::DIRTY_POSITION;
|
||||
}
|
||||
}
|
||||
|
@ -1144,12 +1159,19 @@ void EntityItem::updateVelocityInDomainUnits(const glm::vec3& value) {
|
|||
}
|
||||
|
||||
void EntityItem::updateVelocity(const glm::vec3& value) {
|
||||
if (glm::distance(_velocity, value) > MIN_VELOCITY_DELTA) {
|
||||
if (value == _previousVelocityFromServer) {
|
||||
if (glm::length(value) < MIN_VELOCITY_DELTA) {
|
||||
_velocity = ENTITY_ITEM_ZERO_VEC3;
|
||||
} else {
|
||||
_velocity = value;
|
||||
}
|
||||
} else if (glm::distance(_velocity, value) > MIN_VELOCITY_DELTA) {
|
||||
if (glm::length(value) < MIN_VELOCITY_DELTA) {
|
||||
_velocity = ENTITY_ITEM_ZERO_VEC3;
|
||||
} else {
|
||||
_velocity = value;
|
||||
}
|
||||
_previousVelocityFromServer = value;
|
||||
_dirtyFlags |= EntityItem::DIRTY_VELOCITY;
|
||||
}
|
||||
}
|
||||
|
@ -1167,20 +1189,38 @@ void EntityItem::updateGravityInDomainUnits(const glm::vec3& value) {
|
|||
}
|
||||
|
||||
void EntityItem::updateGravity(const glm::vec3& value) {
|
||||
if ( glm::distance(_gravity, value) > MIN_GRAVITY_DELTA) {
|
||||
if (value == _previousGravityFromServer) {
|
||||
_gravity = value;
|
||||
} else if (glm::distance(_gravity, value) > MIN_GRAVITY_DELTA) {
|
||||
_gravity = value;
|
||||
_previousGravityFromServer = value;
|
||||
_dirtyFlags |= EntityItem::DIRTY_VELOCITY;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateAcceleration(const glm::vec3& value) {
|
||||
_acceleration = value;
|
||||
_dirtyFlags |= EntityItem::DIRTY_VELOCITY;
|
||||
if (value == _previousAccelerationFromServer) {
|
||||
_acceleration = value;
|
||||
} else if (glm::distance(_acceleration, value) > MIN_ACCELERATION_DELTA) {
|
||||
_acceleration = value;
|
||||
_previousAccelerationFromServer = value;
|
||||
_dirtyFlags |= EntityItem::DIRTY_VELOCITY;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateAngularVelocity(const glm::vec3& value) {
|
||||
if (glm::distance(_angularVelocity, value) > MIN_SPIN_DELTA) {
|
||||
_angularVelocity = value;
|
||||
if (value == _previousAngularVelocityFromServer) {
|
||||
if (glm::length(value) < MIN_SPIN_DELTA) {
|
||||
_angularVelocity = ENTITY_ITEM_ZERO_VEC3;
|
||||
} else {
|
||||
_angularVelocity = value;
|
||||
}
|
||||
} else if (glm::distance(_angularVelocity, value) > MIN_SPIN_DELTA) {
|
||||
if (glm::length(value) < MIN_SPIN_DELTA) {
|
||||
_angularVelocity = ENTITY_ITEM_ZERO_VEC3;
|
||||
} else {
|
||||
_angularVelocity = value;
|
||||
}
|
||||
_dirtyFlags |= EntityItem::DIRTY_VELOCITY;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ public:
|
|||
|
||||
// perform linear extrapolation for SimpleEntitySimulation
|
||||
void simulate(const quint64& now);
|
||||
void simulateKinematicMotion(float timeElapsed);
|
||||
void simulateKinematicMotion(float timeElapsed, bool setFlags=true);
|
||||
|
||||
virtual bool needsToCallUpdate() const { return false; }
|
||||
|
||||
|
@ -368,6 +368,13 @@ protected:
|
|||
uint32_t _dirtyFlags; // things that have changed from EXTERNAL changes (via script or packet) but NOT from simulation
|
||||
|
||||
EntityTreeElement* _element; // back pointer to containing Element
|
||||
|
||||
glm::vec3 _previousPositionFromServer;
|
||||
glm::quat _previousRotationFromServer;
|
||||
glm::vec3 _previousVelocityFromServer;
|
||||
glm::vec3 _previousAngularVelocityFromServer;
|
||||
glm::vec3 _previousGravityFromServer;
|
||||
glm::vec3 _previousAccelerationFromServer;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -189,21 +189,21 @@ float EntityMotionState::computeMass(const ShapeInfo& shapeInfo) const {
|
|||
}
|
||||
|
||||
bool EntityMotionState::shouldSendUpdate(uint32_t simulationFrame) {
|
||||
if (getShouldClaimSimulationOwnership()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool baseResult = this->ObjectMotionState::shouldSendUpdate(simulationFrame);
|
||||
|
||||
if (!baseResult) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getShouldClaimSimulationOwnership()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
const QUuid& myNodeID = nodeList->getSessionUUID();
|
||||
const QUuid& simulatorID = _entity->getSimulatorID();
|
||||
|
||||
if (simulatorID != myNodeID) {
|
||||
if (simulatorID != myNodeID && !simulatorID.isNull()) {
|
||||
// some other Node owns the simulating of this, so don't broadcast the results of local simulation.
|
||||
return false;
|
||||
}
|
||||
|
@ -286,15 +286,18 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
|
|||
QUuid myNodeID = nodeList->getSessionUUID();
|
||||
QUuid simulatorID = _entity->getSimulatorID();
|
||||
|
||||
if (getShouldClaimSimulationOwnership()) {
|
||||
_entity->setSimulatorID(myNodeID);
|
||||
properties.setSimulatorID(myNodeID);
|
||||
setShouldClaimSimulationOwnership(false);
|
||||
if (simulatorID.isNull() && !(zeroSpeed && zeroSpin)) {
|
||||
// the entity is moving and no node has claimed simulation ownership. try to claim it.
|
||||
setShouldClaimSimulationOwnership(true);
|
||||
}
|
||||
|
||||
if (simulatorID == myNodeID && zeroSpeed && zeroSpin) {
|
||||
// we are the simulator and the object has stopped. give up "simulator" status
|
||||
_entity->setSimulatorID(QUuid());
|
||||
if (getShouldClaimSimulationOwnership()) {
|
||||
// _entity->setSimulatorID(myNodeID);
|
||||
properties.setSimulatorID(myNodeID);
|
||||
setShouldClaimSimulationOwnership(false);
|
||||
} else if (simulatorID == myNodeID && zeroSpeed && zeroSpin) {
|
||||
// we are the simulator and the entity has stopped. give up "simulator" status
|
||||
// _entity->setSimulatorID(QUuid());
|
||||
properties.setSimulatorID(QUuid());
|
||||
}
|
||||
|
||||
|
|
|
@ -119,8 +119,10 @@ void PhysicsEngine::entityChangedInternal(EntityItem* entity) {
|
|||
assert(entity);
|
||||
void* physicsInfo = entity->getPhysicsInfo();
|
||||
if (physicsInfo) {
|
||||
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(physicsInfo);
|
||||
_incomingChanges.insert(motionState);
|
||||
if ((entity->getDirtyFlags() & (HARD_DIRTY_PHYSICS_FLAGS | EASY_DIRTY_PHYSICS_FLAGS)) > 0) {
|
||||
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(physicsInfo);
|
||||
_incomingChanges.insert(motionState);
|
||||
}
|
||||
} else {
|
||||
// try to add this entity again (maybe something changed such that it will work this time)
|
||||
addEntity(entity);
|
||||
|
@ -366,15 +368,46 @@ void PhysicsEngine::stepNonPhysicalKinematics(const quint64& now) {
|
|||
}
|
||||
}
|
||||
|
||||
void PhysicsEngine::computeCollisionEvents() {
|
||||
BT_PROFILE("computeCollisionEvents");
|
||||
|
||||
void PhysicsEngine::doOwnershipInfection(const btCollisionObject* objectA, const btCollisionObject* objectB) {
|
||||
if (!objectA || !objectB) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
QUuid myNodeID = nodeList->getSessionUUID();
|
||||
|
||||
const btCollisionObject* characterCollisionObject =
|
||||
_characterController ? _characterController->getCollisionObject() : NULL;
|
||||
|
||||
ObjectMotionState* a = static_cast<ObjectMotionState*>(objectA->getUserPointer());
|
||||
ObjectMotionState* b = static_cast<ObjectMotionState*>(objectB->getUserPointer());
|
||||
EntityItem* entityA = a ? a->getEntity() : NULL;
|
||||
EntityItem* entityB = b ? b->getEntity() : NULL;
|
||||
bool aIsDynamic = entityA && !objectA->isStaticOrKinematicObject();
|
||||
bool bIsDynamic = entityB && !objectB->isStaticOrKinematicObject();
|
||||
|
||||
// collisions cause infectious spread of simulation-ownership. we also attempt to take
|
||||
// ownership of anything that collides with our avatar.
|
||||
if ((aIsDynamic && entityA->getSimulatorID() == myNodeID) ||
|
||||
(a && a->getShouldClaimSimulationOwnership()) ||
|
||||
(objectA == characterCollisionObject)) {
|
||||
if (bIsDynamic) {
|
||||
b->setShouldClaimSimulationOwnership(true);
|
||||
}
|
||||
}
|
||||
if ((bIsDynamic && entityB->getSimulatorID() == myNodeID) ||
|
||||
(b && b->getShouldClaimSimulationOwnership()) ||
|
||||
(objectB == characterCollisionObject)) {
|
||||
if (aIsDynamic) {
|
||||
a->setShouldClaimSimulationOwnership(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PhysicsEngine::computeCollisionEvents() {
|
||||
BT_PROFILE("computeCollisionEvents");
|
||||
|
||||
// update all contacts every frame
|
||||
int numManifolds = _collisionDispatcher->getNumManifolds();
|
||||
for (int i = 0; i < numManifolds; ++i) {
|
||||
|
@ -393,31 +426,12 @@ void PhysicsEngine::computeCollisionEvents() {
|
|||
|
||||
ObjectMotionState* a = static_cast<ObjectMotionState*>(objectA->getUserPointer());
|
||||
ObjectMotionState* b = static_cast<ObjectMotionState*>(objectB->getUserPointer());
|
||||
EntityItem* entityA = a ? a->getEntity() : NULL;
|
||||
EntityItem* entityB = b ? b->getEntity() : NULL;
|
||||
bool aIsDynamic = entityA && !objectA->isStaticOrKinematicObject();
|
||||
bool bIsDynamic = entityB && !objectB->isStaticOrKinematicObject();
|
||||
|
||||
if (a || b) {
|
||||
// the manifold has up to 4 distinct points, but only extract info from the first
|
||||
_contactMap[ContactKey(a, b)].update(_numContactFrames, contactManifold->getContactPoint(0), _originOffset);
|
||||
}
|
||||
// collisions cause infectious spread of simulation-ownership. we also attempt to take
|
||||
// ownership of anything that collides with our avatar.
|
||||
if ((aIsDynamic && entityA->getSimulatorID() == myNodeID) ||
|
||||
(a && a->getShouldClaimSimulationOwnership()) ||
|
||||
(objectA == characterCollisionObject)) {
|
||||
if (bIsDynamic) {
|
||||
b->setShouldClaimSimulationOwnership(true);
|
||||
}
|
||||
}
|
||||
if ((bIsDynamic && entityB->getSimulatorID() == myNodeID) ||
|
||||
(b && b->getShouldClaimSimulationOwnership()) ||
|
||||
(objectB == characterCollisionObject)) {
|
||||
if (aIsDynamic) {
|
||||
a->setShouldClaimSimulationOwnership(true);
|
||||
}
|
||||
}
|
||||
|
||||
doOwnershipInfection(objectA, objectB);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -453,6 +467,16 @@ void PhysicsEngine::computeCollisionEvents() {
|
|||
if (type == CONTACT_EVENT_TYPE_END) {
|
||||
ContactMap::iterator iterToDelete = contactItr;
|
||||
++contactItr;
|
||||
|
||||
// const ContactKey& contactKey = (*iterToDelete).first;
|
||||
// const ObjectMotionState* objectMotionStateA = static_cast<ObjectMotionState*>(contactKey._a);
|
||||
// const ObjectMotionState* objectMotionStateB = static_cast<ObjectMotionState*>(contactKey._b);
|
||||
// const btCollisionObject* objectA =
|
||||
// objectMotionStateA ? static_cast<const btCollisionObject*>(objectMotionStateA->getRigidBody()) : NULL;
|
||||
// const btCollisionObject* objectB =
|
||||
// objectMotionStateB ? static_cast<const btCollisionObject*>(objectMotionStateB->getRigidBody()) : NULL;
|
||||
// doOwnershipInfection(objectA, objectB);
|
||||
|
||||
_contactMap.erase(iterToDelete);
|
||||
} else {
|
||||
++contactItr;
|
||||
|
@ -576,11 +600,16 @@ void PhysicsEngine::removeObjectFromBullet(ObjectMotionState* motionState) {
|
|||
assert(motionState);
|
||||
btRigidBody* body = motionState->getRigidBody();
|
||||
|
||||
// set the about-to-be-deleted entity active in order to wake up the island it's part of. this is done
|
||||
// so that anything resting on top of it will fall.
|
||||
// body->setActivationState(ACTIVE_TAG);
|
||||
EntityItem* entity = static_cast<EntityMotionState*>(motionState)->getEntity();
|
||||
bump(entity);
|
||||
// activate this before deleting it so that anything resting on it will begin to fall.
|
||||
//
|
||||
// body->activate();
|
||||
//
|
||||
// motionState->setShouldClaimSimulationOwnership(true);
|
||||
// computeCollisionEvents();
|
||||
//
|
||||
EntityItem* entityItem = motionState ? motionState->getEntity() : NULL;
|
||||
bump(entityItem);
|
||||
|
||||
|
||||
if (body) {
|
||||
const btCollisionShape* shape = body->getCollisionShape();
|
||||
|
|
|
@ -89,16 +89,19 @@ public:
|
|||
|
||||
void dumpNextStats() { _dumpNextStats = true; }
|
||||
|
||||
void bump(EntityItem* bumpEntity);
|
||||
|
||||
private:
|
||||
/// \param motionState pointer to Object's MotionState
|
||||
void removeObjectFromBullet(ObjectMotionState* motionState);
|
||||
|
||||
void removeContacts(ObjectMotionState* motionState);
|
||||
|
||||
void doOwnershipInfection(const btCollisionObject* objectA, const btCollisionObject* objectB);
|
||||
|
||||
// return 'true' of update was successful
|
||||
bool updateObjectHard(btRigidBody* body, ObjectMotionState* motionState, uint32_t flags);
|
||||
void updateObjectEasy(btRigidBody* body, ObjectMotionState* motionState, uint32_t flags);
|
||||
void bump(EntityItem* bumpEntity);
|
||||
|
||||
btClock _clock;
|
||||
btDefaultCollisionConfiguration* _collisionConfig = NULL;
|
||||
|
|
Loading…
Reference in a new issue