-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'adminotundra/InterestManagement' into t…
…undra2 # Conflicts: # src/Core/TundraProtocolModule/SyncManager.cpp
- Loading branch information
Showing
9 changed files
with
4,455 additions
and
4,112 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
// For conditions of distribution and use, see copyright notice in LICENSE | ||
|
||
#pragma once | ||
|
||
#include "StableHeaders.h" | ||
#define MATH_OGRE_INTEROP | ||
#include "EntityPrioritizer.h" | ||
#include "SyncState.h" | ||
|
||
#include "Profiler.h" | ||
#include "Scene.h" | ||
#include "EC_Placeable.h" | ||
#include "EC_RigidBody.h" | ||
#include "EC_Mesh.h" | ||
#include "OgreMeshAsset.h" | ||
//#include "EC_Sound.h" | ||
|
||
void DefaultEntityPrioritizer::ComputeSyncPriorities(EntitySyncStateMap &entities, const float3 &observerPos,const float3 &observerRot) | ||
{ | ||
// IDEA: could cache observerPos and observerRot and recompute priorities only of those are changed. | ||
// But of constantly moving objects it's probably good to recompute priorities every once in a while even if | ||
// the observer doesn't move. | ||
if (!observerPos.IsFinite() || !observerRot.IsFinite()) | ||
return; // camera information not received yet. | ||
ScenePtr scn = scene.lock(); | ||
if (!scn) | ||
return; | ||
|
||
PROFILE(DefaultEntityPrioritizer_ComputeSyncPriorities); | ||
for(EntitySyncStateMap::iterator it = entities.begin(); it != entities.end(); ++it) | ||
{ | ||
EntitySyncState &entityState = it->second; | ||
Entity *entity = scn->EntityById(entityState.id).get(); /**< @todo Use EntityWeakPtr in EntitySyncState when available */ | ||
if (!entity) | ||
continue; // we (might) end up here e.g. when entity was just deleted | ||
|
||
/// @todo Check do we end up computing sync prio for local entities | ||
|
||
shared_ptr<EC_Placeable> placeable = entity->Component<EC_Placeable>(); | ||
shared_ptr<EC_Mesh> mesh = entity->Component<EC_Mesh>(); | ||
shared_ptr<EC_RigidBody> rigidBody = entity->Component<EC_RigidBody>(); | ||
|
||
/// @todo sound sources | ||
/* | ||
shared_ptr<EC_Sound> sound = entity->Component<EC_Sound>(); | ||
if (sound) | ||
{ | ||
if (sound->spatial.Get() && placeable) | ||
{ | ||
float r = sound->soundOuterRadius.Get(); | ||
r *= r; | ||
entityState.priority = 4.f * pi * r / observerPos.DistanceSq(placeable->WorldPosition()); | ||
} | ||
else | ||
entityState.priority = inf; | ||
} | ||
*/ | ||
/// @todo Handle terrains | ||
//shared_ptr<EC_Terrain> terrain = entity->Component<EC_Terrain>(); | ||
//if (terrain) { ... } | ||
|
||
if (!placeable) | ||
{ | ||
/// @todo Should handle special case entities with rigid body but no placeable? | ||
//if (rigidBody) | ||
// Non-spatial (probably), use max priority | ||
/// @todo Can have f.ex. Terrain component that has its own transform, but it can use Placeable too. | ||
entityState.priority = inf; | ||
} | ||
else if (placeable && !mesh) | ||
{ | ||
// Spatial, but no mesh, for now use a harcoded priority of 20 (updateInterval = 1 / (priority * relevance), | ||
// so will probably yield the default SyncManager's update period 1/20th of a second | ||
entityState.priority = 20.f; | ||
/// @todo retrieve/calculate bounding volumes of possible billboards, particle systems, lights, etc. | ||
/// Not going to be easy with Ogre though, especially when running in headless mode. | ||
} | ||
else if (placeable && mesh) | ||
{ | ||
OBB worldObb; | ||
if (scn->GetFramework()->IsHeadless()) | ||
{ | ||
// On headless mode, force mesh asset load in order to be able to inspect its AABB. | ||
if (!mesh->MeshAsset() && !mesh->meshRef.Get().ref.trimmed().isEmpty()) | ||
{ | ||
mesh->ForceMeshLoad(); | ||
continue; // compute the priority next time when mesh asset is available | ||
} | ||
// EC_Mesh::WorldOBB not usable in headless mode (no Ogre::Entity available), | ||
// so we must dig the bounding volume information from OgreMeshAsset (Ogre::Mesh) instead. | ||
/// @todo For some meshes (f.ex. floor of the Avatar scene) there seems to be significant discrepancy | ||
// between the OBB values when running as headless or not. Investigate. | ||
Ogre::MeshPtr ogreMesh = mesh->MeshAsset() ? mesh->MeshAsset()->ogreMesh : Ogre::MeshPtr(); | ||
if (ogreMesh.isNull()) | ||
LogWarning("SyncManager::ComputeSyncPriorities: " + entity->ToString().toStdString() + " has null Ogre mesh " + mesh->GetMeshName()); | ||
worldObb = !ogreMesh.isNull() ? AABB(ogreMesh->getBounds()) : OBB(); | ||
worldObb.Transform(placeable->LocalToWorld()); | ||
} | ||
else | ||
worldObb = mesh->WorldOBB(); | ||
float sizeSq = worldObb.SurfaceArea(); | ||
sizeSq *= sizeSq; | ||
float distanceSq = observerPos.DistanceSq(placeable->WorldPosition()); | ||
entityState.priority = sizeSq/distanceSq; | ||
//LogDebug(QString("%1 sizeSq %2 distanceSq %3").arg(entity->ToString()).arg(sizeSq).arg(distanceSq)); | ||
} | ||
|
||
/// @todo Take direction and velocity of rigid bodies into account | ||
//if (rigibBody) | ||
/// @todo Hardcoded relevancy of 10 for entities with RigidBody component and 1 for others for now. | ||
/// @todo Movement of non-physical entities is too jerky. | ||
entityState.relevancy = rigidBody /*entity->Component("EC_Avatar")*/ ? 10.f : 1.f; | ||
//LogDebug(QString("%1 P %2 R %3 P*R %4 syncRate %5").arg(entity->ToString()).arg( | ||
//entityState.priority).arg(entityState.relevancy).arg(entityState.FinalPriority()).arg(entityState.ComputePrioritizedUpdateInterval(updatePeriod_))); | ||
} | ||
} | ||
|
||
void DefaultEntityPrioritizer::ComputeSyncPriorities(EntitySyncState &entityState, const float3 &observerPos, const float3 &observerRot) | ||
{ | ||
EntitySyncStateMap m; | ||
m[entityState.id] = entityState; | ||
ComputeSyncPriorities(m, observerPos, observerRot); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// For conditions of distribution and use, see copyright notice in LICENSE | ||
|
||
#pragma once | ||
|
||
#include "TundraProtocolModuleFwd.h" | ||
#include "TundraProtocolModuleApi.h" | ||
#include "SceneFwd.h" | ||
|
||
/// Subclass and provide the implementation to SyncManager to perform application-specific entity prioritizing. | ||
/** The base class implementations of functions are no-ops. | ||
@remark Interest management */ | ||
class TUNDRAPROTOCOL_MODULE_API EntityPrioritizer | ||
{ | ||
public: | ||
/// Computes priorities provided entity sync states. | ||
/// @todo In addition, or instead, could provide a function with begin and end iterators as input. This could useful | ||
/// when dealing when very large container and only a fixed number of priority calculation would be wanted per frame. | ||
virtual void ComputeSyncPriorities(EntitySyncStateMap & UNUSED_PARAM(entities), const float3 & UNUSED_PARAM(observerPos),const float3 & UNUSED_PARAM(observerRot)) | ||
{ | ||
} | ||
|
||
/// @overload | ||
virtual void ComputeSyncPriorities(EntitySyncState & UNUSED_PARAM(entityState), const float3 & UNUSED_PARAM(observerPos), const float3 & UNUSED_PARAM(observerRot)) | ||
{ | ||
} | ||
|
||
/// @todo Provide virtual Sort() function? Prioritizer could sort then dirty queue using custom predicates. | ||
}; | ||
|
||
/// Subclass to perform application-specific entity prioritizing. | ||
class TUNDRAPROTOCOL_MODULE_API DefaultEntityPrioritizer : public EntityPrioritizer | ||
{ | ||
public: | ||
explicit DefaultEntityPrioritizer(const SceneWeakPtr &syncedScene) : scene(syncedScene) {} | ||
/// EntityPrioritizer override | ||
void ComputeSyncPriorities(EntitySyncStateMap &entities, const float3 &observerPos,const float3 &observerRot); | ||
/// EntityPrioritizer override | ||
void ComputeSyncPriorities(EntitySyncState &entityState, const float3 &observerPos, const float3 &observerRot); | ||
|
||
SceneWeakPtr scene; | ||
}; |
Oops, something went wrong.