mirror of
https://github.com/overte-org/overte.git
synced 2025-06-15 23:59:43 +02:00
Merge pull request #7522 from ZappoMan/optimizeFindZones
optimize checkEnterLeaveEntities() to do distance check and stationary checks less frequently
This commit is contained in:
commit
74633ca8c8
4 changed files with 72 additions and 27 deletions
26
examples/entityScripts/changeColorOnEnterLeave.js
Normal file
26
examples/entityScripts/changeColorOnEnterLeave.js
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
//
|
||||||
|
// changeColorOnEnterLeave.js
|
||||||
|
// examples/entityScripts
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on 3/31/16.
|
||||||
|
// Copyright 2016 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
(function(){
|
||||||
|
function getRandomInt(min, max) {
|
||||||
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.enterEntity = function(myID) {
|
||||||
|
print("enterEntity() myID:" + myID);
|
||||||
|
Entities.editEntity(myID, { color: { red: getRandomInt(128,255), green: getRandomInt(128,255), blue: getRandomInt(128,255)} });
|
||||||
|
};
|
||||||
|
|
||||||
|
this.leaveEntity = function(myID) {
|
||||||
|
print("leaveEntity() myID:" + myID);
|
||||||
|
Entities.editEntity(myID, { color: { red: getRandomInt(128,255), green: getRandomInt(128,255), blue: getRandomInt(128,255)} });
|
||||||
|
};
|
||||||
|
})
|
|
@ -3357,9 +3357,10 @@ void Application::update(float deltaTime) {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
PROFILE_RANGE_EX("HarvestChanges", 0xffffff00, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
PROFILE_RANGE_EX("HarvestChanges", 0xffffff00, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
||||||
PerformanceTimer perfTimer("havestChanges");
|
PerformanceTimer perfTimer("harvestChanges");
|
||||||
if (_physicsEngine->hasOutgoingChanges()) {
|
if (_physicsEngine->hasOutgoingChanges()) {
|
||||||
getEntities()->getTree()->withWriteLock([&] {
|
getEntities()->getTree()->withWriteLock([&] {
|
||||||
|
PerformanceTimer perfTimer("handleOutgoingChanges");
|
||||||
const VectorOfMotionStates& outgoingChanges = _physicsEngine->getOutgoingChanges();
|
const VectorOfMotionStates& outgoingChanges = _physicsEngine->getOutgoingChanges();
|
||||||
_entitySimulation.handleOutgoingChanges(outgoingChanges, Physics::getSessionUUID());
|
_entitySimulation.handleOutgoingChanges(outgoingChanges, Physics::getSessionUUID());
|
||||||
avatarManager->handleOutgoingChanges(outgoingChanges);
|
avatarManager->handleOutgoingChanges(outgoingChanges);
|
||||||
|
@ -3375,6 +3376,7 @@ void Application::update(float deltaTime) {
|
||||||
// Collision events (and their scripts) must not be handled when we're locked, above. (That would risk
|
// Collision events (and their scripts) must not be handled when we're locked, above. (That would risk
|
||||||
// deadlock.)
|
// deadlock.)
|
||||||
_entitySimulation.handleCollisionEvents(collisionEvents);
|
_entitySimulation.handleCollisionEvents(collisionEvents);
|
||||||
|
|
||||||
// NOTE: the getEntities()->update() call below will wait for lock
|
// NOTE: the getEntities()->update() call below will wait for lock
|
||||||
// and will simulate entity motion (the EntityTree has been given an EntitySimulation).
|
// and will simulate entity motion (the EntityTree has been given an EntitySimulation).
|
||||||
getEntities()->update(); // update the models...
|
getEntities()->update(); // update the models...
|
||||||
|
|
|
@ -130,6 +130,7 @@ void EntityTreeRenderer::setTree(OctreePointer newTree) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityTreeRenderer::update() {
|
void EntityTreeRenderer::update() {
|
||||||
|
PerformanceTimer perfTimer("ETRupdate");
|
||||||
if (_tree && !_shuttingDown) {
|
if (_tree && !_shuttingDown) {
|
||||||
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);
|
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);
|
||||||
tree->update();
|
tree->update();
|
||||||
|
@ -159,12 +160,14 @@ void EntityTreeRenderer::update() {
|
||||||
|
|
||||||
bool EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(const glm::vec3& avatarPosition, QVector<EntityItemID>* entitiesContainingAvatar) {
|
bool EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(const glm::vec3& avatarPosition, QVector<EntityItemID>* entitiesContainingAvatar) {
|
||||||
bool didUpdate = false;
|
bool didUpdate = false;
|
||||||
float radius = 1.0f; // for now, assume 1 meter radius
|
float radius = 0.01f; // for now, assume 0.01 meter radius, because we actually check the point inside later
|
||||||
QVector<EntityItemPointer> foundEntities;
|
QVector<EntityItemPointer> foundEntities;
|
||||||
|
|
||||||
// find the entities near us
|
// find the entities near us
|
||||||
// don't let someone else change our tree while we search
|
// don't let someone else change our tree while we search
|
||||||
_tree->withReadLock([&] {
|
_tree->withReadLock([&] {
|
||||||
|
|
||||||
|
// FIXME - if EntityTree had a findEntitiesContainingPoint() this could theoretically be a little faster
|
||||||
std::static_pointer_cast<EntityTree>(_tree)->findEntities(avatarPosition, radius, foundEntities);
|
std::static_pointer_cast<EntityTree>(_tree)->findEntities(avatarPosition, radius, foundEntities);
|
||||||
|
|
||||||
// Whenever you're in an intersection between zones, we will always choose the smallest zone.
|
// Whenever you're in an intersection between zones, we will always choose the smallest zone.
|
||||||
|
@ -173,33 +176,35 @@ bool EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(const glm::vec3&
|
||||||
_bestZoneVolume = std::numeric_limits<float>::max();
|
_bestZoneVolume = std::numeric_limits<float>::max();
|
||||||
|
|
||||||
// create a list of entities that actually contain the avatar's position
|
// create a list of entities that actually contain the avatar's position
|
||||||
foreach(EntityItemPointer entity, foundEntities) {
|
for (auto& entity : foundEntities) {
|
||||||
|
auto isZone = entity->getType() == EntityTypes::Zone;
|
||||||
|
auto hasScript = !entity->getScript().isEmpty();
|
||||||
|
|
||||||
|
// only consider entities that are zones or have scripts, all other entities can
|
||||||
|
// be ignored because they can have events fired on them.
|
||||||
|
// FIXME - this could be optimized further by determining if the script is loaded
|
||||||
|
// and if it has either an enterEntity or leaveEntity method
|
||||||
|
if (isZone || hasScript) {
|
||||||
|
// now check to see if the point contains our entity, this can be expensive if
|
||||||
|
// the entity has a collision hull
|
||||||
if (entity->contains(avatarPosition)) {
|
if (entity->contains(avatarPosition)) {
|
||||||
if (entitiesContainingAvatar) {
|
if (entitiesContainingAvatar) {
|
||||||
*entitiesContainingAvatar << entity->getEntityItemID();
|
*entitiesContainingAvatar << entity->getEntityItemID();
|
||||||
}
|
}
|
||||||
|
|
||||||
// if this entity is a zone, use this time to determine the bestZone
|
// if this entity is a zone and visible, determine if it is the bestZone
|
||||||
if (entity->getType() == EntityTypes::Zone) {
|
if (isZone && entity->getVisible()) {
|
||||||
if (!entity->getVisible()) {
|
|
||||||
#ifdef WANT_DEBUG
|
|
||||||
qCDebug(entitiesrenderer) << "not visible";
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
float entityVolumeEstimate = entity->getVolumeEstimate();
|
float entityVolumeEstimate = entity->getVolumeEstimate();
|
||||||
if (entityVolumeEstimate < _bestZoneVolume) {
|
if (entityVolumeEstimate < _bestZoneVolume) {
|
||||||
_bestZoneVolume = entityVolumeEstimate;
|
_bestZoneVolume = entityVolumeEstimate;
|
||||||
_bestZone = std::dynamic_pointer_cast<ZoneEntityItem>(entity);
|
_bestZone = std::dynamic_pointer_cast<ZoneEntityItem>(entity);
|
||||||
}
|
} else if (entityVolumeEstimate == _bestZoneVolume) {
|
||||||
else if (entityVolumeEstimate == _bestZoneVolume) {
|
// in the case of the volume being equal, we will use the
|
||||||
|
// EntityItemID to deterministically pick one entity over the other
|
||||||
if (!_bestZone) {
|
if (!_bestZone) {
|
||||||
_bestZoneVolume = entityVolumeEstimate;
|
_bestZoneVolume = entityVolumeEstimate;
|
||||||
_bestZone = std::dynamic_pointer_cast<ZoneEntityItem>(entity);
|
_bestZone = std::dynamic_pointer_cast<ZoneEntityItem>(entity);
|
||||||
}
|
} else if (entity->getEntityItemID() < _bestZone->getEntityItemID()) {
|
||||||
else {
|
|
||||||
// in the case of the volume being equal, we will use the
|
|
||||||
// EntityItemID to deterministically pick one entity over the other
|
|
||||||
if (entity->getEntityItemID() < _bestZone->getEntityItemID()) {
|
|
||||||
_bestZoneVolume = entityVolumeEstimate;
|
_bestZoneVolume = entityVolumeEstimate;
|
||||||
_bestZone = std::dynamic_pointer_cast<ZoneEntityItem>(entity);
|
_bestZone = std::dynamic_pointer_cast<ZoneEntityItem>(entity);
|
||||||
}
|
}
|
||||||
|
@ -208,7 +213,6 @@ bool EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(const glm::vec3&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (_bestZone != oldBestZone) {
|
if (_bestZone != oldBestZone) {
|
||||||
applyZonePropertiesToScene(_bestZone);
|
applyZonePropertiesToScene(_bestZone);
|
||||||
|
@ -217,13 +221,24 @@ bool EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(const glm::vec3&
|
||||||
});
|
});
|
||||||
return didUpdate;
|
return didUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityTreeRenderer::checkEnterLeaveEntities() {
|
bool EntityTreeRenderer::checkEnterLeaveEntities() {
|
||||||
|
PerformanceTimer perfTimer("checkEnterLeaveEntities");
|
||||||
|
auto now = usecTimestampNow();
|
||||||
bool didUpdate = false;
|
bool didUpdate = false;
|
||||||
|
|
||||||
if (_tree && !_shuttingDown) {
|
if (_tree && !_shuttingDown) {
|
||||||
glm::vec3 avatarPosition = _viewState->getAvatarPosition();
|
glm::vec3 avatarPosition = _viewState->getAvatarPosition();
|
||||||
|
|
||||||
if (avatarPosition != _lastAvatarPosition) {
|
// we want to check our enter/leave state if we've moved a significant amount, or
|
||||||
|
// if some amount of time has elapsed since we last checked. We check the time
|
||||||
|
// elapsed because zones or entities might have been created "around us" while we've
|
||||||
|
// been stationary
|
||||||
|
auto movedEnough = glm::distance(avatarPosition, _lastAvatarPosition) > ZONE_CHECK_DISTANCE;
|
||||||
|
auto enoughTimeElapsed = (now - _lastZoneCheck) > ZONE_CHECK_INTERVAL;
|
||||||
|
|
||||||
|
if (movedEnough || enoughTimeElapsed) {
|
||||||
|
_lastZoneCheck = now;
|
||||||
QVector<EntityItemID> entitiesContainingAvatar;
|
QVector<EntityItemID> entitiesContainingAvatar;
|
||||||
didUpdate = findBestZoneAndMaybeContainingEntities(avatarPosition, &entitiesContainingAvatar);
|
didUpdate = findBestZoneAndMaybeContainingEntities(avatarPosition, &entitiesContainingAvatar);
|
||||||
|
|
||||||
|
@ -248,8 +263,6 @@ bool EntityTreeRenderer::checkEnterLeaveEntities() {
|
||||||
}
|
}
|
||||||
_currentEntitiesInside = entitiesContainingAvatar;
|
_currentEntitiesInside = entitiesContainingAvatar;
|
||||||
_lastAvatarPosition = avatarPosition;
|
_lastAvatarPosition = avatarPosition;
|
||||||
} else {
|
|
||||||
didUpdate = findBestZoneAndMaybeContainingEntities(avatarPosition, nullptr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return didUpdate;
|
return didUpdate;
|
||||||
|
|
|
@ -178,6 +178,10 @@ private:
|
||||||
std::shared_ptr<ZoneEntityItem> _bestZone;
|
std::shared_ptr<ZoneEntityItem> _bestZone;
|
||||||
float _bestZoneVolume;
|
float _bestZoneVolume;
|
||||||
|
|
||||||
|
quint64 _lastZoneCheck { 0 };
|
||||||
|
const quint64 ZONE_CHECK_INTERVAL = USECS_PER_MSEC * 100; // ~10hz
|
||||||
|
const float ZONE_CHECK_DISTANCE = 0.001f;
|
||||||
|
|
||||||
glm::vec3 _previousKeyLightColor;
|
glm::vec3 _previousKeyLightColor;
|
||||||
float _previousKeyLightIntensity;
|
float _previousKeyLightIntensity;
|
||||||
float _previousKeyLightAmbientIntensity;
|
float _previousKeyLightAmbientIntensity;
|
||||||
|
|
Loading…
Reference in a new issue