mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 19:59:28 +02:00
Merge pull request #3493 from ZappoMan/moreWorkOnCollidingEntitites
handled multiple collisions correctly, and don't collide if fully enclosed
This commit is contained in:
commit
3ea9923240
2 changed files with 87 additions and 76 deletions
|
@ -78,6 +78,11 @@ void EntityCollisionSystem::emitGlobalEntityCollisionWithEntity(EntityItem* enti
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityCollisionSystem::updateCollisionWithVoxels(EntityItem* entity) {
|
void EntityCollisionSystem::updateCollisionWithVoxels(EntityItem* entity) {
|
||||||
|
|
||||||
|
if (entity->getIgnoreForCollisions() || !entity->getCollisionsWillMove()) {
|
||||||
|
return; // bail early if this entity is to be ignored or wont move
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec3 center = entity->getPosition() * (float)(TREE_SCALE);
|
glm::vec3 center = entity->getPosition() * (float)(TREE_SCALE);
|
||||||
float radius = entity->getRadius() * (float)(TREE_SCALE);
|
float radius = entity->getRadius() * (float)(TREE_SCALE);
|
||||||
const float ELASTICITY = 0.4f;
|
const float ELASTICITY = 0.4f;
|
||||||
|
@ -120,95 +125,95 @@ void EntityCollisionSystem::updateCollisionWithEntities(EntityItem* entityA) {
|
||||||
bool shapeCollisions = _entities->findShapeCollisions(&entityA->getCollisionShapeInMeters(),
|
bool shapeCollisions = _entities->findShapeCollisions(&entityA->getCollisionShapeInMeters(),
|
||||||
collisions, Octree::NoLock, &shapeCollisionsAccurate);
|
collisions, Octree::NoLock, &shapeCollisionsAccurate);
|
||||||
|
|
||||||
|
|
||||||
if (shapeCollisions) {
|
if (shapeCollisions) {
|
||||||
for(int i = 0; i < collisions.size(); i++) {
|
for(int i = 0; i < collisions.size(); i++) {
|
||||||
|
|
||||||
CollisionInfo* collision = collisions[i];
|
CollisionInfo* collision = collisions[i];
|
||||||
penetration = collision->_penetration;
|
penetration = collision->_penetration;
|
||||||
entityB = static_cast<EntityItem*>(collision->_extraData);
|
entityB = static_cast<EntityItem*>(collision->_extraData);
|
||||||
|
|
||||||
// TODO: how to handle multiple collisions?
|
// NOTE: 'penetration' is the depth that 'entityA' overlaps 'entityB'. It points from A into B.
|
||||||
break;
|
glm::vec3 penetrationInTreeUnits = penetration / (float)(TREE_SCALE);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shapeCollisions) {
|
|
||||||
// NOTE: 'penetration' is the depth that 'entityA' overlaps 'entityB'. It points from A into B.
|
|
||||||
glm::vec3 penetrationInTreeUnits = penetration / (float)(TREE_SCALE);
|
|
||||||
|
|
||||||
// Even if the Entities overlap... when the Entities are already moving appart
|
// Even if the Entities overlap... when the Entities are already moving appart
|
||||||
// we don't want to count this as a collision.
|
// we don't want to count this as a collision.
|
||||||
glm::vec3 relativeVelocity = entityA->getVelocity() - entityB->getVelocity();
|
glm::vec3 relativeVelocity = entityA->getVelocity() - entityB->getVelocity();
|
||||||
|
|
||||||
bool wantToMoveA = entityA->getCollisionsWillMove();
|
|
||||||
bool wantToMoveB = entityB->getCollisionsWillMove();
|
|
||||||
bool movingTowardEachOther = glm::dot(relativeVelocity, penetrationInTreeUnits) > 0.0f;
|
|
||||||
|
|
||||||
// only do collisions if the entities are moving toward each other and one or the other
|
|
||||||
// of the entities are movable from collisions
|
|
||||||
bool doCollisions = movingTowardEachOther && (wantToMoveA || wantToMoveB);
|
|
||||||
|
|
||||||
if (doCollisions) {
|
|
||||||
quint64 now = usecTimestampNow();
|
|
||||||
|
|
||||||
CollisionInfo collision;
|
|
||||||
collision._penetration = penetration;
|
|
||||||
// for now the contactPoint is the average between the the two paricle centers
|
|
||||||
collision._contactPoint = (0.5f * (float)TREE_SCALE) * (entityA->getPosition() + entityB->getPosition());
|
|
||||||
emitGlobalEntityCollisionWithEntity(entityA, entityB, collision);
|
|
||||||
|
|
||||||
glm::vec3 axis = glm::normalize(penetration);
|
|
||||||
glm::vec3 axialVelocity = glm::dot(relativeVelocity, axis) * axis;
|
|
||||||
|
|
||||||
float massA = entityA->getMass();
|
|
||||||
float massB = entityB->getMass();
|
|
||||||
float totalMass = massA + massB;
|
|
||||||
float massRatioA = (2.0f * massB / totalMass);
|
|
||||||
float massRatioB = (2.0f * massA / totalMass);
|
|
||||||
|
|
||||||
// in the event that one of our entities is non-moving, then fix up these ratios
|
|
||||||
if (wantToMoveA && !wantToMoveB) {
|
|
||||||
massRatioA = 2.0f;
|
|
||||||
massRatioB = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!wantToMoveA && wantToMoveB) {
|
|
||||||
massRatioA = 0.0f;
|
|
||||||
massRatioB = 2.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// unless the entity is configured to not be moved by collision, calculate it's new position
|
bool fullyEnclosedCollision = glm::length(penetrationInTreeUnits) > entityA->getLargestDimension();
|
||||||
// and velocity and apply it
|
|
||||||
if (wantToMoveA) {
|
|
||||||
// handle Entity A
|
|
||||||
glm::vec3 newVelocityA = entityA->getVelocity() - axialVelocity * massRatioA;
|
|
||||||
glm::vec3 newPositionA = entityA->getPosition() - 0.5f * penetrationInTreeUnits;
|
|
||||||
|
|
||||||
EntityItemProperties propertiesA = entityA->getProperties();
|
bool wantToMoveA = entityA->getCollisionsWillMove();
|
||||||
EntityItemID idA(entityA->getID());
|
bool wantToMoveB = entityB->getCollisionsWillMove();
|
||||||
propertiesA.setVelocity(newVelocityA * (float)TREE_SCALE);
|
bool movingTowardEachOther = glm::dot(relativeVelocity, penetrationInTreeUnits) > 0.0f;
|
||||||
propertiesA.setPosition(newPositionA * (float)TREE_SCALE);
|
|
||||||
propertiesA.setLastEdited(now);
|
// only do collisions if the entities are moving toward each other and one or the other
|
||||||
|
// of the entities are movable from collisions
|
||||||
|
bool doCollisions = !fullyEnclosedCollision && movingTowardEachOther && (wantToMoveA || wantToMoveB);
|
||||||
|
|
||||||
|
if (doCollisions) {
|
||||||
|
|
||||||
|
quint64 now = usecTimestampNow();
|
||||||
|
|
||||||
_entities->updateEntity(idA, propertiesA);
|
CollisionInfo collision;
|
||||||
_packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, idA, propertiesA);
|
collision._penetration = penetration;
|
||||||
}
|
// for now the contactPoint is the average between the the two paricle centers
|
||||||
|
collision._contactPoint = (0.5f * (float)TREE_SCALE) * (entityA->getPosition() + entityB->getPosition());
|
||||||
|
emitGlobalEntityCollisionWithEntity(entityA, entityB, collision);
|
||||||
|
|
||||||
// unless the entity is configured to not be moved by collision, calculate it's new position
|
glm::vec3 axis = glm::normalize(penetration);
|
||||||
// and velocity and apply it
|
glm::vec3 axialVelocity = glm::dot(relativeVelocity, axis) * axis;
|
||||||
if (wantToMoveB) {
|
|
||||||
glm::vec3 newVelocityB = entityB->getVelocity() + axialVelocity * massRatioB;
|
|
||||||
glm::vec3 newPositionB = entityB->getPosition() + 0.5f * penetrationInTreeUnits;
|
|
||||||
|
|
||||||
EntityItemProperties propertiesB = entityB->getProperties();
|
float massA = entityA->getMass();
|
||||||
|
float massB = entityB->getMass();
|
||||||
|
float totalMass = massA + massB;
|
||||||
|
float massRatioA = (2.0f * massB / totalMass);
|
||||||
|
float massRatioB = (2.0f * massA / totalMass);
|
||||||
|
|
||||||
EntityItemID idB(entityB->getID());
|
// in the event that one of our entities is non-moving, then fix up these ratios
|
||||||
propertiesB.setVelocity(newVelocityB * (float)TREE_SCALE);
|
if (wantToMoveA && !wantToMoveB) {
|
||||||
propertiesB.setPosition(newPositionB * (float)TREE_SCALE);
|
massRatioA = 2.0f;
|
||||||
propertiesB.setLastEdited(now);
|
massRatioB = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
_entities->updateEntity(idB, propertiesB);
|
if (!wantToMoveA && wantToMoveB) {
|
||||||
_packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, idB, propertiesB);
|
massRatioA = 0.0f;
|
||||||
}
|
massRatioB = 2.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// unless the entity is configured to not be moved by collision, calculate it's new position
|
||||||
|
// and velocity and apply it
|
||||||
|
if (wantToMoveA) {
|
||||||
|
// handle Entity A
|
||||||
|
glm::vec3 newVelocityA = entityA->getVelocity() - axialVelocity * massRatioA;
|
||||||
|
glm::vec3 newPositionA = entityA->getPosition() - 0.5f * penetrationInTreeUnits;
|
||||||
|
|
||||||
|
EntityItemProperties propertiesA = entityA->getProperties();
|
||||||
|
EntityItemID idA(entityA->getID());
|
||||||
|
propertiesA.setVelocity(newVelocityA * (float)TREE_SCALE);
|
||||||
|
propertiesA.setPosition(newPositionA * (float)TREE_SCALE);
|
||||||
|
propertiesA.setLastEdited(now);
|
||||||
|
|
||||||
|
_entities->updateEntity(idA, propertiesA);
|
||||||
|
_packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, idA, propertiesA);
|
||||||
|
}
|
||||||
|
|
||||||
|
// unless the entity is configured to not be moved by collision, calculate it's new position
|
||||||
|
// and velocity and apply it
|
||||||
|
if (wantToMoveB) {
|
||||||
|
glm::vec3 newVelocityB = entityB->getVelocity() + axialVelocity * massRatioB;
|
||||||
|
glm::vec3 newPositionB = entityB->getPosition() + 0.5f * penetrationInTreeUnits;
|
||||||
|
|
||||||
|
EntityItemProperties propertiesB = entityB->getProperties();
|
||||||
|
|
||||||
|
EntityItemID idB(entityB->getID());
|
||||||
|
propertiesB.setVelocity(newVelocityB * (float)TREE_SCALE);
|
||||||
|
propertiesB.setPosition(newPositionB * (float)TREE_SCALE);
|
||||||
|
propertiesB.setLastEdited(now);
|
||||||
|
|
||||||
|
_entities->updateEntity(idB, propertiesB);
|
||||||
|
_packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, idB, propertiesB);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -220,6 +225,10 @@ void EntityCollisionSystem::updateCollisionWithAvatars(EntityItem* entity) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (entity->getIgnoreForCollisions() || !entity->getCollisionsWillMove()) {
|
||||||
|
return; // bail early if this entity is to be ignored or wont move
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec3 center = entity->getPosition() * (float)(TREE_SCALE);
|
glm::vec3 center = entity->getPosition() * (float)(TREE_SCALE);
|
||||||
float radius = entity->getRadius() * (float)(TREE_SCALE);
|
float radius = entity->getRadius() * (float)(TREE_SCALE);
|
||||||
const float ELASTICITY = 0.9f;
|
const float ELASTICITY = 0.9f;
|
||||||
|
|
|
@ -558,7 +558,9 @@ bool EntityTreeElement::findShapeCollisions(const Shape* shape, CollisionList& c
|
||||||
|
|
||||||
// entities that are set for ignore for collisions then don't consider them for collision
|
// entities that are set for ignore for collisions then don't consider them for collision
|
||||||
const Shape* otherCollisionShape = &entity->getCollisionShapeInMeters();
|
const Shape* otherCollisionShape = &entity->getCollisionShapeInMeters();
|
||||||
if (shape != otherCollisionShape && !entity->getIgnoreForCollisions()) {
|
|
||||||
|
bool ignoreForCollisions = entity->getIgnoreForCollisions();
|
||||||
|
if (shape != otherCollisionShape && !ignoreForCollisions) {
|
||||||
if (ShapeCollider::collideShapes(shape, otherCollisionShape, collisions)) {
|
if (ShapeCollider::collideShapes(shape, otherCollisionShape, collisions)) {
|
||||||
CollisionInfo* lastCollision = collisions.getLastCollision();
|
CollisionInfo* lastCollision = collisions.getLastCollision();
|
||||||
lastCollision->_extraData = entity;
|
lastCollision->_extraData = entity;
|
||||||
|
|
Loading…
Reference in a new issue