Showing the changes to libraries/entities/src/EntityCollisionSystem.cpp (1 of 6 files). Show all
Unified · Split
| @@ -99,9 +99,6 @@ void EntityCollisionSystem::updateCollisionWithVoxels(EntityItem* entity) { · 98 unmodified lines | ||
| 99 | 99 | VoxelDetail* voxelDetails = NULL; |
| 100 | 100 | if (_voxels->findSpherePenetration(center, radius, collisionInfo._penetration, (void**)&voxelDetails)) { |
| 101 | 101 | |
| 102 | − // let the Entities run their collision scripts if they have them | |
| 103 | − //entity->collisionWithVoxel(voxelDetails, collisionInfo._penetration); | |
| 104 | − | |
| 105 | 102 | // findSpherePenetration() only computes the penetration but we also want some other collision info |
| 106 | 103 | // so we compute it ourselves here. Note that we must multiply scale by TREE_SCALE when feeding |
| 107 | 104 | // the results to systems outside of this octree reference frame. |
| @@ -112,9 +109,8 @@ void EntityCollisionSystem::updateCollisionWithVoxels(EntityItem* entity) { · 4 unmodified lines | ||
| 112 | 109 | // we must scale back down to the octree reference frame before updating the Entity properties |
| 113 | 110 | collisionInfo._penetration /= (float)(TREE_SCALE); |
| 114 | 111 | collisionInfo._contactPoint /= (float)(TREE_SCALE); |
| 115 | − entity->applyHardCollision(collisionInfo); | |
| 116 | − queueEntityPropertiesUpdate(entity); | |
| 117 | 112 | |
| 113 | + applyHardCollision(entity, collisionInfo); | |
| 118 | 114 | delete voxelDetails; // cleanup returned details |
| 119 | 115 | } |
| 120 | 116 | } |
| @@ -138,9 +134,6 @@ void EntityCollisionSystem::updateCollisionWithEntities(EntityItem* entityA) { · 17 unmodified lines | ||
| 138 | 134 | if (doCollisions) { |
| 139 | 135 | quint64 now = usecTimestampNow(); |
| 140 | 136 | |
| 141 | − entityA->collisionWithEntity(entityB, penetration); | |
| 142 | − entityB->collisionWithEntity(entityA, penetration * -1.0f); // the penetration is reversed | |
| 143 | − | |
| 144 | 137 | CollisionInfo collision; |
| 145 | 138 | collision._penetration = penetration; |
| 146 | 139 | // for now the contactPoint is the average between the the two paricle centers |
| @@ -188,9 +181,6 @@ void EntityCollisionSystem::updateCollisionWithEntities(EntityItem* entityA) { · 41 unmodified lines | ||
| 188 | 181 | |
| 189 | 182 | void EntityCollisionSystem::updateCollisionWithAvatars(EntityItem* entity) { |
| 190 | 183 | |
| 191 | − // TODO: implement support for colliding with avatars | |
| 192 | − | |
| 193 | −#if 0 | |
| 194 | 184 | // Entities that are in hand, don't collide with avatars |
| 195 | 185 | if (!_avatars) { |
| 196 | 186 | return; |
| @@ -200,7 +190,6 @@ void EntityCollisionSystem::updateCollisionWithAvatars(EntityItem* entity) { · 3 unmodified lines | ||
| 200 | 190 | float radius = entity->getRadius() * (float)(TREE_SCALE); |
| 201 | 191 | const float ELASTICITY = 0.9f; |
| 202 | 192 | const float DAMPING = 0.1f; |
| 203 | − const float COLLISION_FREQUENCY = 0.5f; | |
| 204 | 193 | glm::vec3 penetration; |
| 205 | 194 | |
| 206 | 195 | _collisions.clear(); |
| @@ -227,22 +216,57 @@ void EntityCollisionSystem::updateCollisionWithAvatars(EntityItem* entity) { · 20 unmodified lines | ||
| 227 | 216 | // only collide when Entity and collision point are moving toward each other |
| 228 | 217 | // (doing this prevents some "collision snagging" when Entity penetrates the object) |
| 229 | 218 | collision->_penetration /= (float)(TREE_SCALE); |
| 230 | − entity->applyHardCollision(*collision); | |
| 231 | − queueEntityPropertiesUpdate(entity); | |
| 219 | + applyHardCollision(entity, *collision); | |
| 232 | 220 | } |
| 233 | 221 | } |
| 234 | 222 | } |
| 235 | 223 | } |
| 236 | − | |
| 237 | −#endif | |
| 238 | 224 | } |
| 239 | 225 | |
| 240 | −void EntityCollisionSystem::queueEntityPropertiesUpdate(EntityItem* entity) { | |
| 241 | − // queue the result for sending to the Entity server | |
| 226 | +void EntityCollisionSystem::applyHardCollision(EntityItem* entity, const CollisionInfo& collisionInfo) { | |
| 227 | + // HALTING_* params are determined using expected acceleration of gravity over some timescale. | |
| 228 | + // This is a HACK for entities that bounce in a 1.0 gravitational field and should eventually be made more universal. | |
| 229 | + const float HALTING_ENTITY_PERIOD = 0.0167f; // ~1/60th of a second | |
| 230 | + const float HALTING_ENTITY_SPEED = 9.8 * HALTING_ENTITY_PERIOD / (float)(TREE_SCALE); | |
| 231 | + | |
| 232 | + // | |
| 233 | + // Update the entity in response to a hard collision. Position will be reset exactly | |
| 234 | + // to outside the colliding surface. Velocity will be modified according to elasticity. | |
| 235 | + // | |
| 236 | + // if elasticity = 0.0, collision is inelastic (vel normal to collision is lost) | |
| 237 | + // if elasticity = 1.0, collision is 100% elastic. | |
| 238 | + // | |
| 239 | + glm::vec3 position = entity->getPosition(); | |
| 240 | + glm::vec3 velocity = entity->getVelocity(); | |
| 241 | + | |
| 242 | + const float EPSILON = 0.0f; | |
| 243 | + glm::vec3 relativeVelocity = collisionInfo._addedVelocity - velocity; | |
| 244 | + float velocityDotPenetration = glm::dot(relativeVelocity, collisionInfo._penetration); | |
| 245 | + if (velocityDotPenetration < EPSILON) { | |
| 246 | + // entity is moving into collision surface | |
| 247 | + // | |
| 248 | + // TODO: do something smarter here by comparing the mass of the entity vs that of the other thing | |
| 249 | + // (other's mass could be stored in the Collision Info). The smaller mass should surrender more | |
| 250 | + // position offset and should slave more to the other's velocity in the static-friction case. | |
| 251 | + position -= collisionInfo._penetration; | |
| 252 | + | |
| 253 | + if (glm::length(relativeVelocity) < HALTING_ENTITY_SPEED) { | |
| 254 | + // static friction kicks in and entities moves with colliding object | |
| 255 | + velocity = collisionInfo._addedVelocity; | |
| 256 | + } else { | |
| 257 | + glm::vec3 direction = glm::normalize(collisionInfo._penetration); | |
| 258 | + velocity += glm::dot(relativeVelocity, direction) * (1.0f + collisionInfo._elasticity) * direction; // dynamic reflection | |
| 259 | + velocity += glm::clamp(collisionInfo._damping, 0.0f, 1.0f) * (relativeVelocity - glm::dot(relativeVelocity, direction) * direction); // dynamic friction | |
| 260 | + } | |
| 261 | + } | |
| 262 | + | |
| 242 | 263 | EntityItemProperties properties = entity->getProperties(); |
| 243 | 264 | EntityItemID entityItemID(entity->getID()); |
| 244 | 265 | |
| 245 | − properties.setPosition(entity->getPosition() * (float)TREE_SCALE); | |
| 246 | − properties.setVelocity(entity->getVelocity() * (float)TREE_SCALE); | |
| 266 | + properties.setPosition(position * (float)TREE_SCALE); | |
| 267 | + properties.setVelocity(velocity * (float)TREE_SCALE); | |
| 268 | + properties.setLastEdited(usecTimestampNow()); | |
| 269 | + | |
| 270 | + _entities->updateEntity(entityItemID, properties); | |
| 247 | 271 | _packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, entityItemID, properties); |
| 248 | 272 | } |