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 std::vector<MaterialInstanceHandle> debugTileTreeDepthColorMaterials;
159 };
160
161 //
162 // Current state for a OGC3DTilesComponent
163 //
165 struct State {
166 std::unordered_map<uint64_t, std::vector<OGC3DTilesSystem::LoadedModel>> tileCache; // map[tileId] = vector<LoadedTile>
167 std::unordered_set<uint64_t> pendingModelRequests; // set[tileId]
168 std::unordered_map<uint64_t, EntityPtr> bboxIndicatorCache; // map[tileId] = AxisBoxEntity
169 std::unordered_map<uint32_t, std::unordered_map<uint64_t, OGC3DTilesSubtree::Subtree*>> subtreeCache; // map[subtreeLevel][cachekey] = Subtree
170 std::unordered_map<std::string, OGC3DTilesTileset::Tileset*> subTilesets; // map[URL] = TilesetPtr
171 std::unordered_map<std::string, std::pair<OGC3DTilesSystem::TileCandidate, ModelHandle>> modelRequests; // map[URL] = {tile, ModelHandle}
172 std::unordered_map<std::string, OGC3DTiles::Coord> subtreeRequests; // map[URL] = coord
173 std::unordered_map<uint64_t, Cogs::Core::DataFetcherManager::FetchId> subtreeFetchIds; // map[GUID] = FetchId
174 double timestampOfLastTraversal = 0.0;
175 bool candidateForDelayedTraversal = false; // If true, the tileset might need a traversal after the grace-period as it could be outside the view-frustum.
176 };
177 std::unordered_map<const OGC3DTilesTileset::Tileset*, State> states;
178
179 std::unordered_map<std::string, std::pair<uint64_t, const OGC3DTilesTileset::Tileset*>> subTilesetRequests; // map[URL] = pair<tileId, ParentTilesetPtr>
180 std::vector<const OGC3DTilesTileset::Tileset*> tilesets; // Loaded tilesets. The first tileset is always the main tileset.
181 std::set<std::string> loadedSubTilesets; // set[URL]. A set of URLs for loaded sub-tilesets.
182
183 Entity* parentEntity = nullptr;
184 uint32_t uniqueComponentId = 0;
185 glm::dmat4 originalRootTransform;
186 std::string baseURL = "";
187 std::string additionalURLParameters = "";
188 std::string tileBaseURL = "";
189 std::string optionalAccessKey = ""; // NOTE: All optional access-keys must be in the form "key=value", not just value.
190 std::string optionalSessionKey = "";
191 float detailFactor = 1.0;
192 MaterialInstanceHandle overrideMaterial;
193 bool requiresTraversal = false;
194
195 unsigned int numberOfModelsBeingPrepared = 0; // Num models not ready yet in this frame
196 bool showTileBBoxes = false;
197 bool neverDiscardRootTiles = true;
198 bool waitForTileSiblings = true;
199 bool enableCaching = false;
200 bool colorTileAccordingToTreeDepth = false;
201 bool dontRenderLeaves = false;
202 bool loadAllSiblings = false;
203
204 Cogs::Core::DataFetcherManager::FetchId assetsFetchId = Cogs::Core::DataFetcherManager::NoFetchId;
205 std::unordered_map<uint64_t, Cogs::Core::DataFetcherManager::FetchId> tilesetFetchIds; // map[GUID] = FetchId
206
207 struct Statistics {
208 int traversedDepth = 0;
209 int numberOfCancelledRequests = 0;
210 int numberOfPendingRequests = 0;
211 int numberOfVisitedSubTilesets = 0;
212 };
213 Statistics statistics;
214 };
215
217 std::unique_ptr<OGC3DTilesData> data;
218 };
219 }
220}
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