From b5a28730eac73c5eabe54a582504af0a13e8786d Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 14 May 2015 14:41:32 -0700 Subject: [PATCH 1/2] Filter out low-penetration continuous contact from all entity collision activity including scripts: We don't want sound for these. This appears to avoid the Entities.getEntityProperties() deadlock within entity scripts. Variable names: energyPercentOfFull => energyFactorOfFull, because the range is 0-1, not 0-100. COLLISION_SOUND_COMPRESSION => COLLISION_SOUND_COMPRESSION_RANGE (portion of full dynamic range) Tune constants: COLLISION_ENERGY_AT_FULL_VOLUME 10 => 1 COLLISION_MINIMUM_VOLUME 0.01 => 0.001 COLLISION_SOUND_COMPRESSION_RANGE 0.5 => 0.95 Refer to SoundCache later, after filtering for collision threshold. --- .../src/EntityTreeRenderer.cpp | 38 +++++++++++-------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 3cd5c9a268..158ca17242 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -1119,27 +1119,29 @@ void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityT if (collisionSoundURL.isEmpty()) { return; } - SharedSoundPointer sound = DependencyManager::get().data()->getSound(QUrl(collisionSoundURL)); - if (!sound->isReady()) { - return; - } - const float mass = entity->computeMass(); const float COLLISION_PENTRATION_TO_VELOCITY = 50; // as a subsitute for RELATIVE entity->getVelocity() const float linearVelocity = glm::length(collision.penetration) * COLLISION_PENTRATION_TO_VELOCITY; const float energy = mass * linearVelocity * linearVelocity / 2.0f; const glm::vec3 position = collision.contactPoint; - const float COLLISION_ENERGY_AT_FULL_VOLUME = 10.0f; - const float COLLISION_MINIMUM_VOLUME = 0.01f; - const float energyPercentOfFull = fmin(1.0f, energy / COLLISION_ENERGY_AT_FULL_VOLUME); - //qCDebug(entitiesrenderer) << energyPercentOfFull << energy << " " << " " << linearVelocity << " " << mass; - if (energyPercentOfFull < COLLISION_MINIMUM_VOLUME) { + const float COLLISION_ENERGY_AT_FULL_VOLUME = 1.0f; + const float COLLISION_MINIMUM_VOLUME = 0.001f; + const float energyFactorOfFull = fmin(1.0f, energy / COLLISION_ENERGY_AT_FULL_VOLUME); + //qCDebug(entitiesrenderer) << collisionSoundURL << energyFactorOfFull << energy << collision.type << "/" << glm::length(collision.penetration); + if (energyFactorOfFull < COLLISION_MINIMUM_VOLUME) { return; } - // This is a hack. Quiet sound aren't really heard at all, so we compress everything to the range 0.5-1.0, if we play it all. - const float COLLISION_SOUND_COMPRESSION = 0.5f; - const float volume = (energyPercentOfFull * COLLISION_SOUND_COMPRESSION) + (1.0f - COLLISION_SOUND_COMPRESSION); - //qCDebug(entitiesrenderer) << collisionSoundURL << " " << volume << " " << position << " " << sound->isStereo(); + + SharedSoundPointer sound = DependencyManager::get().data()->getSound(QUrl(collisionSoundURL)); + if (!sound->isReady()) { + return; + } + + // This is a hack. Quiet sound aren't really heard at all, so we compress everything to the range [1-c, 1], if we play it all. + const float COLLISION_SOUND_COMPRESSION_RANGE = 0.95f; + float volume = energyFactorOfFull; + volume = (volume * COLLISION_SOUND_COMPRESSION_RANGE) + (1.0f - COLLISION_SOUND_COMPRESSION_RANGE); + qCDebug(entitiesrenderer) << collisionSoundURL << (volume * 10.0f); // This is quite similar to AudioScriptingInterface::playSound() and should probably be refactored. AudioInjectorOptions options; @@ -1166,13 +1168,19 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons if (!_tree || _shuttingDown) { return; } + // Don't respond to small continuous contacts. It causes deadlocks when locking the entityTree. + // Note that any entity script is likely to Entities.getEntityProperties(), which locks the tree. + const float COLLISION_MINUMUM_PENETRATION = 0.001; + if ((collision.type != CONTACT_EVENT_TYPE_START) && (glm::length(collision.penetration) < COLLISION_MINUMUM_PENETRATION)) { + return; + } // See if we should play sounds EntityTree* entityTree = static_cast(_tree); if (!entityTree->tryLockForRead()) { // I don't know why this can happen, but if it does, // the consequences are a deadlock, so bail. - qCDebug(entitiesrenderer) << "NOTICE: skipping collision."; + qCDebug(entitiesrenderer) << "NOTICE: skipping collision type " << collision.type << " penetration " << glm::length(collision.penetration); return; } const QUuid& myNodeID = DependencyManager::get()->getSessionUUID(); From 5accb4d0d28a7fd40ba601d70462e6be9510b901 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 14 May 2015 15:12:31 -0700 Subject: [PATCH 2/2] Remove debug logging. --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 158ca17242..49187c3b2f 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -1127,7 +1127,6 @@ void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityT const float COLLISION_ENERGY_AT_FULL_VOLUME = 1.0f; const float COLLISION_MINIMUM_VOLUME = 0.001f; const float energyFactorOfFull = fmin(1.0f, energy / COLLISION_ENERGY_AT_FULL_VOLUME); - //qCDebug(entitiesrenderer) << collisionSoundURL << energyFactorOfFull << energy << collision.type << "/" << glm::length(collision.penetration); if (energyFactorOfFull < COLLISION_MINIMUM_VOLUME) { return; } @@ -1141,7 +1140,6 @@ void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityT const float COLLISION_SOUND_COMPRESSION_RANGE = 0.95f; float volume = energyFactorOfFull; volume = (volume * COLLISION_SOUND_COMPRESSION_RANGE) + (1.0f - COLLISION_SOUND_COMPRESSION_RANGE); - qCDebug(entitiesrenderer) << collisionSoundURL << (volume * 10.0f); // This is quite similar to AudioScriptingInterface::playSound() and should probably be refactored. AudioInjectorOptions options;