Skip to content

Commit 20fe18b

Browse files
committed
Start using TileLoadRequester to apply GltfModifier after load.
1 parent 0e04d02 commit 20fe18b

File tree

3 files changed

+219
-24
lines changed

3 files changed

+219
-24
lines changed

Cesium3DTilesSelection/include/Cesium3DTilesSelection/GltfModifier.h

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ namespace Cesium3DTilesSelection {
1919

2020
class Tile;
2121
class TilesetMetadata;
22+
class TilesetContentManager;
2223

2324
/**
2425
* @brief The input to the {@link GltfModifier::apply} function.
@@ -85,13 +86,8 @@ class GltfModifier {
8586
WorkerDone,
8687
};
8788

88-
virtual ~GltfModifier() = default;
89-
9089
/** @return The current modifier version, to identify oudated tile models. */
91-
std::optional<int> getCurrentVersion() const {
92-
return (-1 == currentVersion) ? std::nullopt
93-
: std::optional<int>(currentVersion);
94-
}
90+
std::optional<int> getCurrentVersion() const;
9591

9692
/**
9793
* @brief Activates this modifier after it has been constructed in its default
@@ -101,7 +97,36 @@ class GltfModifier {
10197
* the old one without transition.
10298
* See {@link getCurrentVersion}.
10399
*/
104-
void trigger() { ++currentVersion; }
100+
void trigger();
101+
102+
/**
103+
* @brief When this modifier has been triggered at least once, this is the
104+
* method called after a new tile has been loaded, and everytime the
105+
* modifier's version is incremented with {@link trigger}.
106+
*
107+
* This method is called from a worker thread.
108+
*
109+
* @param input The input to the glTF modification.
110+
* @return A future that resolves to a {@link GltfModifierOutput} with the
111+
* new model, or to `std::nullopt` if the model is not modified.
112+
*/
113+
virtual CesiumAsync::Future<std::optional<GltfModifierOutput>>
114+
apply(GltfModifierInput&& input) = 0;
115+
116+
/**
117+
* @brief Called by {@link Tileset} when this instance has been registered
118+
* with it. To add custom behavior on registration, override the other
119+
* overload of this method.
120+
* @private
121+
*/
122+
CesiumAsync::Future<void> onRegister(
123+
TilesetContentManager& contentManager,
124+
const TilesetMetadata& tilesetMetadata,
125+
const Tile& rootTile);
126+
127+
protected:
128+
GltfModifier();
129+
virtual ~GltfModifier();
105130

106131
/**
107132
* @brief Notifies this instance that is has been registered with a
@@ -110,6 +135,8 @@ class GltfModifier {
110135
* This method is called after the tileset's root tile is known but
111136
* before {@link Tileset::getRootTileAvailableEvent} has been raised.
112137
*
138+
* This method is called from the main thread.
139+
*
113140
* @param asyncSystem The async system with which to do background work.
114141
* @param pAssetAccessor The asset accessor to use to retrieve any additional
115142
* assets.
@@ -127,26 +154,17 @@ class GltfModifier {
127154
const std::shared_ptr<CesiumAsync::IAssetAccessor>& pAssetAccessor,
128155
const std::shared_ptr<spdlog::logger>& pLogger,
129156
const TilesetMetadata& tilesetMetadata,
130-
const Tile& rootTile) = 0;
131-
132-
/**
133-
* @brief When this modifier has been triggered at least once, this is the
134-
* method called after a new tile has been loaded, and everytime the
135-
* modifier's version is incremented with {@link trigger}.
136-
*
137-
* @param input The input to the glTF modification.
138-
* @return A future that resolves to a {@link GltfModifierOutput} with the
139-
* new model, or to `std::nullopt` if the model is not modified.
140-
*/
141-
virtual CesiumAsync::Future<std::optional<GltfModifierOutput>>
142-
apply(GltfModifierInput&& input) = 0;
157+
const Tile& rootTile);
143158

144159
private:
145160
/** The current version of the modifier, if it has ever been triggered.
146161
* Incremented every time trigger() is called by client code to signal that
147162
* models needs to be reprocessed.
148163
*/
149-
std::atomic_int currentVersion = -1;
164+
std::atomic_int _currentVersion = -1;
165+
166+
class NewVersionLoadRequester;
167+
std::unique_ptr<NewVersionLoadRequester> _pNewVersionLoadRequester;
150168
};
151169

152170
} // namespace Cesium3DTilesSelection
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
#include "TilesetContentManager.h"
2+
3+
#include <Cesium3DTilesSelection/GltfModifier.h>
4+
#include <Cesium3DTilesSelection/TileLoadRequester.h>
5+
6+
namespace Cesium3DTilesSelection {
7+
8+
class GltfModifier::NewVersionLoadRequester : public TileLoadRequester {
9+
public:
10+
NewVersionLoadRequester(GltfModifier* pModifier);
11+
12+
double getWeight() const override { return 1.0; }
13+
bool hasMoreTilesToLoadInWorkerThread() const override;
14+
const Tile* getNextTileToLoadInWorkerThread() override;
15+
bool hasMoreTilesToLoadInMainThread() const override;
16+
const Tile* getNextTileToLoadInMainThread() override;
17+
18+
void notifyOfTrigger();
19+
20+
private:
21+
void addTilesToQueues();
22+
23+
GltfModifier* _pModifier;
24+
const Tile* _pRootTile;
25+
std::vector<Tile::ConstPointer> _workerThreadQueue;
26+
std::vector<Tile::ConstPointer> _mainThreadQueue;
27+
bool _running;
28+
};
29+
30+
GltfModifier::GltfModifier()
31+
: _pNewVersionLoadRequester(
32+
std::make_unique<NewVersionLoadRequester>(this)){};
33+
34+
GltfModifier::~GltfModifier() = default;
35+
36+
std::optional<int> GltfModifier::getCurrentVersion() const {
37+
return (-1 == this->_currentVersion)
38+
? std::nullopt
39+
: std::optional<int>(this->_currentVersion);
40+
}
41+
42+
void GltfModifier::trigger() {
43+
++this->_currentVersion;
44+
this->_pNewVersionLoadRequester->notifyOfTrigger();
45+
}
46+
47+
CesiumAsync::Future<void> GltfModifier::onRegister(
48+
TilesetContentManager& contentManager,
49+
const TilesetMetadata& tilesetMetadata,
50+
const Tile& rootTile) {
51+
contentManager.registerTileRequester(*this->_pNewVersionLoadRequester);
52+
53+
const TilesetExternals& externals = contentManager.getExternals();
54+
return this->onRegister(
55+
externals.asyncSystem,
56+
externals.pAssetAccessor,
57+
externals.pLogger,
58+
tilesetMetadata,
59+
rootTile);
60+
}
61+
62+
CesiumAsync::Future<void> GltfModifier::onRegister(
63+
const CesiumAsync::AsyncSystem& asyncSystem,
64+
const std::shared_ptr<CesiumAsync::IAssetAccessor>& /* pAssetAccessor */,
65+
const std::shared_ptr<spdlog::logger>& /* pLogger */,
66+
const TilesetMetadata& /* tilesetMetadata */,
67+
const Tile& /* rootTile */) {
68+
return asyncSystem.createResolvedFuture();
69+
}
70+
71+
GltfModifier::NewVersionLoadRequester::NewVersionLoadRequester(
72+
GltfModifier* pModifier)
73+
: _pModifier(pModifier),
74+
_pRootTile(nullptr),
75+
_workerThreadQueue(),
76+
_mainThreadQueue(),
77+
_running(false) {}
78+
79+
void GltfModifier::NewVersionLoadRequester::notifyOfTrigger() {
80+
this->_running = true;
81+
this->addTilesToQueues();
82+
}
83+
84+
void GltfModifier::NewVersionLoadRequester::addTilesToQueues() {
85+
CESIUM_ASSERT(this->_pRootTile != nullptr);
86+
LoadedConstTileEnumerator enumerator(this->_pRootTile);
87+
for (const Tile& tile : enumerator) {
88+
TileLoadState state = tile.getState();
89+
90+
// Tiles that are already being loaded will need to finish loading, _then_
91+
// we'll have to apply the modification. Always add them to the queue.
92+
if (state == TileLoadState::ContentLoading) {
93+
this->_workerThreadQueue.emplace_back(&tile);
94+
}
95+
96+
// Tiles that are already loaded only need to be added to the queue if they
97+
// have a glTF and it is the wrong version.
98+
if (state != TileLoadState::ContentLoaded && state != TileLoadState::Done)
99+
continue;
100+
101+
const TileRenderContent* pRenderContent =
102+
tile.getContent().getRenderContent();
103+
if (!pRenderContent)
104+
continue;
105+
106+
if (pRenderContent->getModel().version ==
107+
this->_pModifier->getCurrentVersion()) {
108+
CESIUM_ASSERT(!pRenderContent->getModifiedModel());
109+
continue;
110+
}
111+
112+
if (pRenderContent->getModifiedModel() &&
113+
pRenderContent->getModifiedModel()->version ==
114+
this->_pModifier->getCurrentVersion()) {
115+
// Worker thread GltfModifier::apply done, need to do main thread loading.
116+
this->_mainThreadQueue.emplace_back(&tile);
117+
} else {
118+
this->_workerThreadQueue.emplace_back(&tile);
119+
}
120+
}
121+
}
122+
123+
bool GltfModifier::NewVersionLoadRequester::hasMoreTilesToLoadInWorkerThread()
124+
const {
125+
return !this->_workerThreadQueue.empty();
126+
}
127+
128+
const Tile*
129+
GltfModifier::NewVersionLoadRequester::getNextTileToLoadInWorkerThread() {
130+
if (!this->_running) {
131+
CESIUM_ASSERT(this->_workerThreadQueue.empty());
132+
return nullptr;
133+
}
134+
135+
CESIUM_ASSERT(!this->_workerThreadQueue.empty());
136+
const Tile* pResult = this->_workerThreadQueue.back().get();
137+
this->_workerThreadQueue.pop_back();
138+
139+
if (this->_workerThreadQueue.empty()) {
140+
this->addTilesToQueues();
141+
142+
// If both queues are still empty, we're done.
143+
if (this->_workerThreadQueue.empty() && this->_mainThreadQueue.empty()) {
144+
this->_running = false;
145+
}
146+
}
147+
148+
return pResult;
149+
}
150+
151+
bool GltfModifier::NewVersionLoadRequester::hasMoreTilesToLoadInMainThread()
152+
const {
153+
return !this->_mainThreadQueue.empty();
154+
}
155+
156+
const Tile*
157+
GltfModifier::NewVersionLoadRequester::getNextTileToLoadInMainThread() {
158+
if (!this->_running) {
159+
CESIUM_ASSERT(this->_mainThreadQueue.empty());
160+
return nullptr;
161+
}
162+
163+
CESIUM_ASSERT(!this->_mainThreadQueue.empty());
164+
const Tile* pResult = this->_mainThreadQueue.back().get();
165+
this->_mainThreadQueue.pop_back();
166+
167+
if (this->_mainThreadQueue.empty()) {
168+
this->addTilesToQueues();
169+
170+
// If both queues are still empty, we're done.
171+
if (this->_workerThreadQueue.empty() && this->_mainThreadQueue.empty()) {
172+
this->_running = false;
173+
}
174+
}
175+
176+
return pResult;
177+
}
178+
179+
} // namespace Cesium3DTilesSelection

Cesium3DTilesSelection/src/TilesetContentManager.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -745,9 +745,7 @@ CesiumAsync::Future<void> registerGltfModifier(
745745
pRootTile->getContent().getExternalContent();
746746
return pGltfModifier
747747
->onRegister(
748-
contentManager.getExternals().asyncSystem,
749-
contentManager.getExternals().pAssetAccessor,
750-
contentManager.getExternals().pLogger,
748+
contentManager,
751749
pExternal ? pExternal->metadata : TilesetMetadata(),
752750
*pRootTile)
753751
.catchInMainThread([&contentManager](std::exception&&) {

0 commit comments

Comments
 (0)