Cogs.Core
OGC3DTilesSystem.h
1#pragma once
2
3#include "../OGC3DTiles.h"
4#include "../Components/OGC3DTilesComponent.h"
5
6#include "Context.h"
7#include "Systems/ComponentSystem.h"
8#include "Scene/GetBounds.h"
9#include "Services/TaskManager.h"
10#include "Resources/DataFetcherManager.h"
11
12#include "Foundation/Geometry/Glm.hpp"
13#include "Foundation/Geometry/BoundingBox.hpp"
14#include "Foundation/Platform/Threads.h"
15
16#include <chrono>
17#include <string>
18#include <set>
19#include <unordered_map>
20#include <unordered_set>
21#include <map>
22
23namespace Cogs {
24 namespace Core {
25 namespace OGC3DTilesTileset {
26 struct Tile;
27 struct Tileset;
28 };
29
30 namespace OGC3DTilesSubtree {
31 struct Subtree;
32 }
33
34 struct OGC3DTilesData; // Full definition below
35 struct OGC3DTilesDataHolder;
36 class OGC3DTilesBounds;
37
38 class OGC3DTilesSystem : public ComponentSystemWithDataPool<OGC3DTilesComponent, OGC3DTilesDataHolder>
39 {
41 public:
42
44 ~OGC3DTilesSystem() override;
45
46 static bool componentIsStale(Context* context, uint32_t id);
47
48 void initialize(Context* context) override;
49 void update(Context* context) override;
51 void destroyComponent(ComponentHandle component) override;
52
54 uint64_t tileId;
55 std::vector<std::string> URLs;
56 glm::mat4 transform;
57 Cogs::Geometry::DBoundingBox bbox;
58 uint32_t depth = 0;
59 };
60
61 struct LoadedModel {
62 std::string URL;
63 double timestampLastUsed = 0.0;
64 ModelHandle modelHandle;
65 bool isValid = false;
66 std::string uniqueName;
67 uint32_t frameNumberAtArrival = 0; // The current frame-number when model was received from server
68 };
69
70 private:
71 void initializeTileset(OGC3DTilesComponent* component, OGC3DTilesData* componentState);
72 void traverseTileset(const OGC3DTilesComponent * component, OGC3DTilesData* componentState, const OGC3DTilesTileset::Tileset* tileset, float gracePeriodBeforeTileRemoval);
73
74 uint64_t fetchAndInitializeTileset(const uint64_t tilesetGUID, const std::string& tilesetURL, OGC3DTilesComponent* component, uint32_t uniqueComponentId);
75 Cogs::Core::DataFetcherManager::FetchId fetchAndInitializeAsset(OGC3DTilesComponent* component, uint32_t uniqueComponentId);
76
77 struct Node {
78 bool valid = false;
79 bool replaceRefine = false;
80 TileCandidate tile;
81#if defined(__linux__)
82 // NOTE: The Linux compiler does not allow usage of "unordered_map" with the same 'value' as the
83 // container struct itself (ie. an unordered_map with value of type 'Node').
84 std::map<uint64_t, Node> children;
85#else
86 std::unordered_map<uint64_t, Node> children;
87#endif
88 };
89
91 const OGC3DTilesTileset::Tileset* tileset,
92 const OGC3DTilesTileset::Tile* tile,
93 const std::string& tileIdStr,
94 const glm::mat4& currentTransform,
95 const glm::mat4& globalTransform,
96 std::unordered_set<const OGC3DTilesTileset::Tileset*>& visitedTilesets) const;
97
99 const OGC3DTilesTileset::Tileset* tileset,
100 const OGC3DTiles::Coord& coord,
101 const glm::mat4& globalTransform) const;
102
103 void collectTileCandidates(OGC3DTilesData* componentState, const Node* node, std::unordered_map<uint64_t, TileCandidate>& target) const;
104 void calculateTileVisibilities(OGC3DTilesData* componentState, const OGC3DTilesTileset::Tileset* tileset, const Node* node) const;
105
106 bool allChildrenAreReady(OGC3DTilesData* componentState, const OGC3DTilesTileset::Tileset* tileset, const Node* node) const;
107 bool tileHasReadyContent(OGC3DTilesData* componentState, const OGC3DTilesTileset::Tileset* tileset, uint64_t tileId) const;
108 bool tileHasModelRequests(const OGC3DTilesData* componentState, const OGC3DTilesTileset::Tileset* tileset, uint64_t tileId) const;
109 bool tileHasSubTilesetRequests(const OGC3DTilesData* componentState, uint64_t tileId) const;
110 void setTileVisibility(const OGC3DTilesData* componentState, const OGC3DTilesTileset::Tileset* tileset, uint64_t tileId, bool onoff) const;
111 void setVisibilityForAllTiles(const OGC3DTilesData* componentState, bool onoff) const;
112 bool modelIsReady(const ModelHandle& modelhandle) const;
113
114 size_t pruneTileCache(OGC3DTilesData* componentState, const OGC3DTilesTileset::Tileset* tileset, float gracePeriodBeforeTileRemoval) const;
115 void removeTileFromScene(OGC3DTilesData* componentState, const OGC3DTilesTileset::Tileset* tileset, uint64_t tileId) const;
116 void requestSubTileset(OGC3DTilesData* componentState, const std::string& fullURL, uint64_t tileId, const OGC3DTilesTileset::Tileset* parentTileset) const;
117 void requestSubtree(OGC3DTilesData* componentState, const OGC3DTilesTileset::Tileset* tileset, const OGC3DTiles::Coord& coord) const;
118
119 bool requestModel(OGC3DTilesData* componentState, const OGC3DTilesTileset::Tileset* tileset, const TileCandidate & tile, const std::string URL) const;
120 void loadMissingModels(OGC3DTilesData* componentState, const OGC3DTilesTileset::Tileset* tileset, const std::unordered_map<uint64_t, TileCandidate>& toBeLoaded) const;
121 void addModelToScene(const std::string& uniqueName, TileCandidate tile, ModelHandle handle, const OGC3DTilesData* componentState) const;
122
123 void addBBoxIndicatorToScene(OGC3DTilesData* componentState, const OGC3DTilesTileset::Tileset* tileset, uint64_t tileId, Cogs::Geometry::DBoundingBox box) const;
124 void removeBBoxIndicatorFromScene(OGC3DTilesData* componentState, const OGC3DTilesTileset::Tileset* tileset, uint64_t tileId) const;
125 void cancelStaleModelRequests(OGC3DTilesData* componentState, const OGC3DTilesTileset::Tileset* tileset, const Node& node) const;
126
127 void processModelRequests(OGC3DTilesData* componentState, const OGC3DTilesTileset::Tileset* tileset, uint32_t frameNumber) const;
128 void processSubtreeRequests(const OGC3DTilesComponent* component, OGC3DTilesData* componentState, const OGC3DTilesTileset::Tileset* tileset);
129 void processSubTilesetRequests(const OGC3DTilesComponent* component, OGC3DTilesData* componentState);
130
131 bool hasPendingRequests(const OGC3DTilesData* componentState) const;
132 void cleanupPendingSubtreeRequests(OGC3DTilesData* componentState, const OGC3DTilesTileset::Tileset* tileset) const;
133
134 bool isInsideFrustum(const Cogs::Geometry::DBoundingBox& box) const;
135 glm::dvec3 getCurrentCameraPosition() const;
136
137 static uint64_t makeCacheKey(const OGC3DTiles::Coord& coord);
138 static std::string buildSubtreeURL(const OGC3DTilesData* componentState, const OGC3DTilesTileset::Tileset* tileset, const OGC3DTiles::Coord& coord);
140 std::vector<OGC3DTiles::Coord> getTileCoordChildren(OGC3DTilesData* componentState, const OGC3DTilesTileset::Tileset* tileset, const OGC3DTiles::Coord& parent) const;
141
142 static bool modelIsEmpty(const ModelHandle handle);
143 std::string addOptionalURLParameters(const OGC3DTilesData* componentState, const std::string& url) const;
144 bool extractAndStoreOptionalSessionKeys(OGC3DTilesData* componentState, const std::string& url) const;
145
146 void applyMaterialToAllModels(const OGC3DTilesData* componentState, MaterialInstanceHandle materialHandle);
147 void applyMaterialToModel(const OGC3DTilesSystem::LoadedModel & model, MaterialInstanceHandle materialHandle);
148
149 static void printDebugStats(const OGC3DTilesData* componentState);
150 static std::string compileURL(const std::string& baseURL, const std::string& tilesetPath, const std::string& modelPath);
151
152 OGC3DTilesBounds* bounds = nullptr;
153 std::string accessToken = "";
154
155 double timestampOfLastCameraMovement = 0.0;
156 glm::mat4 lastCameraViewProjection = glm::mat4(-1);
157 };
158
159 //
160 // Current state for a OGC3DTilesComponent
161 //
163 struct State {
164 std::unordered_map<uint64_t, std::vector<OGC3DTilesSystem::LoadedModel>> tileCache; // map[tileId] = vector<LoadedTile>
165 std::unordered_set<uint64_t> pendingModelRequests; // set[tileId]
166 std::unordered_map<uint64_t, EntityPtr> bboxIndicatorCache; // map[tileId] = AxisBoxEntity
167 std::unordered_map<uint32_t, std::unordered_map<uint64_t, OGC3DTilesSubtree::Subtree*>> subtreeCache; // map[subtreeLevel][cachekey] = Subtree
168 std::unordered_map<std::string, OGC3DTilesTileset::Tileset*> subTilesets; // map[URL] = TilesetPtr
169 std::unordered_map<std::string, std::pair<OGC3DTilesSystem::TileCandidate, ModelHandle>> modelRequests; // map[URL] = {tile, ModelHandle}
170 std::unordered_map<std::string, OGC3DTiles::Coord> subtreeRequests; // map[URL] = coord
171 std::unordered_map<uint64_t, Cogs::Core::DataFetcherManager::FetchId> subtreeFetchIds; // map[GUID] = FetchId
172 double timestampOfLastTraversal = 0.0;
173 bool candidateForDelayedTraversal = false; // If true, the tileset might need a traversal after the grace-period as it could be outside the view-frustum.
174 };
175 std::unordered_map<const OGC3DTilesTileset::Tileset*, State> states;
176
177 std::unordered_map<std::string, std::pair<uint64_t, const OGC3DTilesTileset::Tileset*>> subTilesetRequests; // map[URL] = pair<tileId, ParentTilesetPtr>
178 std::vector<const OGC3DTilesTileset::Tileset*> tilesets; // Loaded tilesets. The first tileset is always the main tileset.
179 std::set<std::string> loadedSubTilesets; // set[URL]. A set of URLs for loaded sub-tilesets.
180
181 Entity* parentEntity = nullptr;
182 uint32_t uniqueComponentId = 0;
183 glm::dmat4 originalRootTransform;
184 std::string baseURL = "";
185 std::string additionalURLParameters = "";
186 std::string tileBaseURL = "";
187 std::string optionalAccessKey = ""; // NOTE: All optional access-keys must be in the form "key=value", not just value.
188 std::string optionalSessionKey = "";
189 float detailFactor = 1.0;
190 MaterialInstanceHandle overrideMaterial;
191 bool requiresTraversal = false;
192
193 unsigned int numberOfModelsBeingPrepared = 0; // Num models not ready yet in this frame
194 bool showTileBBoxes = false;
195 bool neverDiscardRootTiles = true;
196 bool waitForTileSiblings = true;
197 bool enableCaching = false;
198 bool colorTileAccordingToTreeDepth = false;
199 bool dontRenderLeaves = false;
200
201 Cogs::Core::DataFetcherManager::FetchId assetsFetchId = Cogs::Core::DataFetcherManager::NoFetchId;
202 std::unordered_map<uint64_t, Cogs::Core::DataFetcherManager::FetchId> tilesetFetchIds; // map[GUID] = FetchId
203
204 struct Statistics {
205 int traversedDepth = 0;
206 int numberOfCancelledRequests = 0;
207 int numberOfPendingRequests = 0;
208 int numberOfVisitedSubTilesets = 0;
209 };
210 Statistics statistics;
211 };
212
214 std::unique_ptr<OGC3DTilesData> data;
215 };
216 }
217}
Container for components, providing composition of dynamic entities.
Definition: Entity.h:18
Context * context
Pointer to the Context instance the system lives in.
void update()
Updates the system state to that of the current frame.
Component system with parallel data per component stored in a pool similar to how the components them...
A Context instance contains all the services, systems and runtime components needed to use Cogs.
Definition: Context.h:83
Node buildImplicitTree(OGC3DTilesData *componentState, const OGC3DTilesTileset::Tileset *tileset, const OGC3DTiles::Coord &coord, const glm::mat4 &globalTransform) const
bool requestModel(OGC3DTilesData *componentState, const OGC3DTilesTileset::Tileset *tileset, const TileCandidate &tile, const std::string URL) const
static uint64_t makeCacheKey(const OGC3DTiles::Coord &coord)
bool allChildrenAreReady(OGC3DTilesData *componentState, const OGC3DTilesTileset::Tileset *tileset, const Node *node) const
void collectTileCandidates(OGC3DTilesData *componentState, const Node *node, std::unordered_map< uint64_t, TileCandidate > &target) const
static bool componentIsStale(Context *context, uint32_t id)
void loadMissingModels(OGC3DTilesData *componentState, const OGC3DTilesTileset::Tileset *tileset, const std::unordered_map< uint64_t, TileCandidate > &toBeLoaded) const
void requestSubtree(OGC3DTilesData *componentState, const OGC3DTilesTileset::Tileset *tileset, const OGC3DTiles::Coord &coord) const
Node buildExplicitTree(OGC3DTilesData *componentState, const OGC3DTilesTileset::Tileset *tileset, const OGC3DTilesTileset::Tile *tile, const std::string &tileIdStr, const glm::mat4 &currentTransform, const glm::mat4 &globalTransform, std::unordered_set< const OGC3DTilesTileset::Tileset * > &visitedTilesets) const
OGC3DTilesSubtree::Subtree * getSubtreeForTileCoord(OGC3DTilesData *componentState, const OGC3DTilesTileset::Tileset *tileset, const OGC3DTiles::Coord &coord) const
bool tileHasReadyContent(OGC3DTilesData *componentState, const OGC3DTilesTileset::Tileset *tileset, uint64_t tileId) const
void cleanupPendingSubtreeRequests(OGC3DTilesData *componentState, const OGC3DTilesTileset::Tileset *tileset) const
bool extractAndStoreOptionalSessionKeys(OGC3DTilesData *componentState, const std::string &url) const
size_t pruneTileCache(OGC3DTilesData *componentState, const OGC3DTilesTileset::Tileset *tileset, float gracePeriodBeforeTileRemoval) const
ComponentHandle createComponent() override
void calculateTileVisibilities(OGC3DTilesData *componentState, const OGC3DTilesTileset::Tileset *tileset, const Node *node) const
void addModelToScene(const std::string &uniqueName, TileCandidate tile, ModelHandle handle, const OGC3DTilesData *componentState) const
void initialize(Context *context) override
Initialize the system.
void destroyComponent(ComponentHandle component) override
Base allocator implementation.
Definition: Allocator.h:30
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
uint32_t ComponentIndex
Type used to track component indexes in pools.
Definition: Component.h:16
Handle to a Component instance.
Definition: Component.h:67