History

handled multiple collisions correctly, and don't collide if fully enclosed

ZappoMan committed 12 years ago

Commit bbd476d1 parent 21b0e312 files · +80 −78Browse files

Showing the changes to libraries/entities/src/EntityCollisionSystem.cpp (1 of 2 files). Show all

Unified · Split

libraries/entities/src/EntityCollisionSystem.cpp+77−77
@@ -120,95 +120,95 @@ void EntityCollisionSystem::updateCollisionWithEntities(EntityItem* entityA) { · 119 unmodified lines
120120 bool shapeCollisions = _entities->findShapeCollisions(&entityA->getCollisionShapeInMeters(),
121121 collisions, Octree::NoLock, &shapeCollisionsAccurate);
122122
123+
123124 if (shapeCollisions) {
124125 for(int i = 0; i < collisions.size(); i++) {
126+
125127 CollisionInfo* collision = collisions[i];
126128 penetration = collision->_penetration;
127129 entityB = static_cast<EntityItem*>(collision->_extraData);
128130
129− // TODO: how to handle multiple collisions?
130− break;
131− }
132− }
133−
134− if (shapeCollisions) {
135− // NOTE: 'penetration' is the depth that 'entityA' overlaps 'entityB'. It points from A into B.
136− glm::vec3 penetrationInTreeUnits = penetration / (float)(TREE_SCALE);
131+ // NOTE: 'penetration' is the depth that 'entityA' overlaps 'entityB'. It points from A into B.
132+ glm::vec3 penetrationInTreeUnits = penetration / (float)(TREE_SCALE);
137133
138− // Even if the Entities overlap... when the Entities are already moving appart
139− // we don't want to count this as a collision.
140− glm::vec3 relativeVelocity = entityA->getVelocity() - entityB->getVelocity();
134+ // Even if the Entities overlap... when the Entities are already moving appart
135+ // we don't want to count this as a collision.
136+ glm::vec3 relativeVelocity = entityA->getVelocity() - entityB->getVelocity();
137+
138+ bool fullyEnclosedCollision = glm::length(penetrationInTreeUnits) > entityA->getLargestDimension();
141139
142− bool wantToMoveA = entityA->getCollisionsWillMove();
143− bool wantToMoveB = entityB->getCollisionsWillMove();
144− bool movingTowardEachOther = glm::dot(relativeVelocity, penetrationInTreeUnits) > 0.0f;
145−
146− // only do collisions if the entities are moving toward each other and one or the other
147− // of the entities are movable from collisions
148− bool doCollisions = movingTowardEachOther && (wantToMoveA || wantToMoveB);
140+ bool wantToMoveA = entityA->getCollisionsWillMove();
141+ bool wantToMoveB = entityB->getCollisionsWillMove();
142+ bool movingTowardEachOther = glm::dot(relativeVelocity, penetrationInTreeUnits) > 0.0f;
149143
150− if (doCollisions) {
151− quint64 now = usecTimestampNow();
144+ // only do collisions if the entities are moving toward each other and one or the other
145+ // of the entities are movable from collisions
146+ bool doCollisions = !fullyEnclosedCollision && movingTowardEachOther && (wantToMoveA || wantToMoveB);
147+
148+ if (doCollisions) {
149+
150+ quint64 now = usecTimestampNow();
152151
153− CollisionInfo collision;
154− collision._penetration = penetration;
155− // for now the contactPoint is the average between the the two paricle centers
156− collision._contactPoint = (0.5f * (float)TREE_SCALE) * (entityA->getPosition() + entityB->getPosition());
157− emitGlobalEntityCollisionWithEntity(entityA, entityB, collision);
158−
159− glm::vec3 axis = glm::normalize(penetration);
160− glm::vec3 axialVelocity = glm::dot(relativeVelocity, axis) * axis;
161−
162− float massA = entityA->getMass();
163− float massB = entityB->getMass();
164− float totalMass = massA + massB;
165− float massRatioA = (2.0f * massB / totalMass);
166− float massRatioB = (2.0f * massA / totalMass);
167−
168− // in the event that one of our entities is non-moving, then fix up these ratios
169− if (wantToMoveA && !wantToMoveB) {
170− massRatioA = 2.0f;
171− massRatioB = 0.0f;
172− }
152+ CollisionInfo collision;
153+ collision._penetration = penetration;
154+ // for now the contactPoint is the average between the the two paricle centers
155+ collision._contactPoint = (0.5f * (float)TREE_SCALE) * (entityA->getPosition() + entityB->getPosition());
156+ emitGlobalEntityCollisionWithEntity(entityA, entityB, collision);
157+
158+ glm::vec3 axis = glm::normalize(penetration);
159+ glm::vec3 axialVelocity = glm::dot(relativeVelocity, axis) * axis;
160+
161+ float massA = entityA->getMass();
162+ float massB = entityB->getMass();
163+ float totalMass = massA + massB;
164+ float massRatioA = (2.0f * massB / totalMass);
165+ float massRatioB = (2.0f * massA / totalMass);
166+
167+ // in the event that one of our entities is non-moving, then fix up these ratios
168+ if (wantToMoveA && !wantToMoveB) {
169+ massRatioA = 2.0f;
170+ massRatioB = 0.0f;
171+ }
173172
174− if (!wantToMoveA && wantToMoveB) {
175− massRatioA = 0.0f;
176− massRatioB = 2.0f;
177− }
173+ if (!wantToMoveA && wantToMoveB) {
174+ massRatioA = 0.0f;
175+ massRatioB = 2.0f;
176+ }
178177
179− // unless the entity is configured to not be moved by collision, calculate it's new position
180− // and velocity and apply it
181− if (wantToMoveA) {
182− // handle Entity A
183− glm::vec3 newVelocityA = entityA->getVelocity() - axialVelocity * massRatioA;
184− glm::vec3 newPositionA = entityA->getPosition() - 0.5f * penetrationInTreeUnits;
185−
186− EntityItemProperties propertiesA = entityA->getProperties();
187− EntityItemID idA(entityA->getID());
188− propertiesA.setVelocity(newVelocityA * (float)TREE_SCALE);
189− propertiesA.setPosition(newPositionA * (float)TREE_SCALE);
190− propertiesA.setLastEdited(now);
191−
192− _entities->updateEntity(idA, propertiesA);
193− _packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, idA, propertiesA);
194− }
195−
196− // unless the entity is configured to not be moved by collision, calculate it's new position
197− // and velocity and apply it
198− if (wantToMoveB) {
199− glm::vec3 newVelocityB = entityB->getVelocity() + axialVelocity * massRatioB;
200− glm::vec3 newPositionB = entityB->getPosition() + 0.5f * penetrationInTreeUnits;
201−
202− EntityItemProperties propertiesB = entityB->getProperties();
203−
204− EntityItemID idB(entityB->getID());
205− propertiesB.setVelocity(newVelocityB * (float)TREE_SCALE);
206− propertiesB.setPosition(newPositionB * (float)TREE_SCALE);
207− propertiesB.setLastEdited(now);
208−
209− _entities->updateEntity(idB, propertiesB);
210− _packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, idB, propertiesB);
211− }
178+ // unless the entity is configured to not be moved by collision, calculate it's new position
179+ // and velocity and apply it
180+ if (wantToMoveA) {
181+ // handle Entity A
182+ glm::vec3 newVelocityA = entityA->getVelocity() - axialVelocity * massRatioA;
183+ glm::vec3 newPositionA = entityA->getPosition() - 0.5f * penetrationInTreeUnits;
184+
185+ EntityItemProperties propertiesA = entityA->getProperties();
186+ EntityItemID idA(entityA->getID());
187+ propertiesA.setVelocity(newVelocityA * (float)TREE_SCALE);
188+ propertiesA.setPosition(newPositionA * (float)TREE_SCALE);
189+ propertiesA.setLastEdited(now);
190+
191+ _entities->updateEntity(idA, propertiesA);
192+ _packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, idA, propertiesA);
193+ }
194+
195+ // unless the entity is configured to not be moved by collision, calculate it's new position
196+ // and velocity and apply it
197+ if (wantToMoveB) {
198+ glm::vec3 newVelocityB = entityB->getVelocity() + axialVelocity * massRatioB;
199+ glm::vec3 newPositionB = entityB->getPosition() + 0.5f * penetrationInTreeUnits;
200+
201+ EntityItemProperties propertiesB = entityB->getProperties();
202+
203+ EntityItemID idB(entityB->getID());
204+ propertiesB.setVelocity(newVelocityB * (float)TREE_SCALE);
205+ propertiesB.setPosition(newPositionB * (float)TREE_SCALE);
206+ propertiesB.setLastEdited(now);
207+
208+ _entities->updateEntity(idB, propertiesB);
209+ _packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, idB, propertiesB);
210+ }
211+ }
212212 }
213213 }
214214 }