mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-02-21 20:39:08 -06:00
Move OpenGL in globebrowsing from constructors into initialization functions
Place entire scene loading into separate thread
This commit is contained in:
@@ -259,17 +259,24 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
|
||||
addPropertySubOwner(_layerManager.get());
|
||||
//addPropertySubOwner(_pointGlobe.get());
|
||||
|
||||
}
|
||||
|
||||
void RenderableGlobe::initializeGL() {
|
||||
_layerManager->initialize();
|
||||
|
||||
_layerManager->update();
|
||||
|
||||
_distanceSwitch.initializeGL();
|
||||
|
||||
// Recompile the shaders directly so that it is not done the first time the render
|
||||
// function is called.
|
||||
_chunkedLodGlobe->recompileShaders();
|
||||
}
|
||||
|
||||
void RenderableGlobe::initializeGL() {
|
||||
_distanceSwitch.initializeGL();
|
||||
}
|
||||
|
||||
void RenderableGlobe::deinitializeGL() {
|
||||
_distanceSwitch.deinitializeGL();
|
||||
|
||||
_layerManager->deinitialize();
|
||||
}
|
||||
|
||||
bool RenderableGlobe::isReady() const {
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace openspace::globebrowsing {
|
||||
ChunkRenderer::ChunkRenderer(std::shared_ptr<Grid> grid,
|
||||
std::shared_ptr<LayerManager> layerManager)
|
||||
: _grid(grid)
|
||||
,_layerManager(layerManager)
|
||||
, _layerManager(layerManager)
|
||||
{
|
||||
_globalLayerShaderManager = std::make_shared<LayerShaderManager>(
|
||||
"GlobalChunkedLodPatch",
|
||||
|
||||
@@ -219,6 +219,18 @@ Layer::Layer(layergroupid::GroupID id, const ghoul::Dictionary& layerDict,
|
||||
addPropertySubOwner(_layerAdjustment);
|
||||
}
|
||||
|
||||
void Layer::initialize() {
|
||||
if (_tileProvider) {
|
||||
_tileProvider->initialize();
|
||||
}
|
||||
}
|
||||
|
||||
void Layer::deinitialize() {
|
||||
if (_tileProvider) {
|
||||
_tileProvider->deinitialize();
|
||||
}
|
||||
}
|
||||
|
||||
ChunkTilePile Layer::getChunkTilePile(const TileIndex& tileIndex, int pileSize) const {
|
||||
if (_tileProvider) {
|
||||
return _tileProvider->getChunkTilePile(tileIndex, pileSize);
|
||||
|
||||
@@ -55,6 +55,9 @@ public:
|
||||
|
||||
Layer(layergroupid::GroupID id, const ghoul::Dictionary& layerDict, LayerGroup& parent);
|
||||
|
||||
void initialize();
|
||||
void deinitialize();
|
||||
|
||||
ChunkTilePile getChunkTilePile(const TileIndex& tileIndex, int pileSize) const;
|
||||
Tile::Status getTileStatus(const TileIndex& index) const;
|
||||
|
||||
|
||||
@@ -79,6 +79,18 @@ LayerGroup::LayerGroup(layergroupid::GroupID id, const ghoul::Dictionary& dict)
|
||||
}
|
||||
}
|
||||
|
||||
void LayerGroup::initialize() {
|
||||
for (const std::shared_ptr<Layer>& l : _layers) {
|
||||
l->initialize();
|
||||
}
|
||||
}
|
||||
|
||||
void LayerGroup::deinitialize() {
|
||||
for (const std::shared_ptr<Layer>& l : _layers) {
|
||||
l->deinitialize();
|
||||
}
|
||||
}
|
||||
|
||||
void LayerGroup::update() {
|
||||
_activeLayers.clear();
|
||||
|
||||
@@ -102,7 +114,7 @@ void LayerGroup::addLayer(const ghoul::Dictionary& layerDict) {
|
||||
}
|
||||
else {
|
||||
_layers.push_back(layer);
|
||||
update();
|
||||
//update();
|
||||
if (_onChangeCallback) {
|
||||
_onChangeCallback();
|
||||
}
|
||||
|
||||
@@ -46,6 +46,9 @@ struct LayerGroup : public properties::PropertyOwner {
|
||||
LayerGroup(layergroupid::GroupID id);
|
||||
LayerGroup(layergroupid::GroupID id, const ghoul::Dictionary& dict);
|
||||
|
||||
void initialize();
|
||||
void deinitialize();
|
||||
|
||||
/// Updates all layers tile providers within this group
|
||||
void update();
|
||||
|
||||
|
||||
@@ -68,6 +68,18 @@ LayerManager::LayerManager(const ghoul::Dictionary& layerGroupsDict)
|
||||
}
|
||||
}
|
||||
|
||||
void LayerManager::initialize() {
|
||||
for (const std::shared_ptr<LayerGroup>& lg : _layerGroups) {
|
||||
lg->initialize();
|
||||
}
|
||||
}
|
||||
|
||||
void LayerManager::deinitialize() {
|
||||
for (const std::shared_ptr<LayerGroup>& lg : _layerGroups) {
|
||||
lg->deinitialize();
|
||||
}
|
||||
}
|
||||
|
||||
void LayerManager::addLayer(layergroupid::GroupID groupId, ghoul::Dictionary layerDict) {
|
||||
ghoul_assert(groupId != layergroupid::Unknown, "Layer group ID must be known");
|
||||
_layerGroups[groupId]->addLayer(layerDict);
|
||||
|
||||
@@ -45,6 +45,9 @@ class LayerManager : public properties::PropertyOwner {
|
||||
public:
|
||||
LayerManager(const ghoul::Dictionary& textureCategoriesDictionary);
|
||||
|
||||
void initialize();
|
||||
void deinitialize();
|
||||
|
||||
void addLayer(layergroupid::GroupID groupId, ghoul::Dictionary layerDict);
|
||||
void deleteLayer(layergroupid::GroupID groupId, std::string layerName);
|
||||
|
||||
|
||||
@@ -84,15 +84,10 @@ TemporalTileProvider::TemporalTileProvider(const ghoul::Dictionary& dictionary)
|
||||
if (hasStart && hasEnd) {
|
||||
const std::string start = dictionary.value<std::string>(KeyPreCacheStartTime);
|
||||
const std::string end = dictionary.value<std::string>(KeyPreCacheEndTime);
|
||||
std::vector<Time> preCacheTimes = _timeQuantizer.quantized(
|
||||
_preCacheTimes = _timeQuantizer.quantized(
|
||||
Time(Time::convertTime(start)),
|
||||
Time(Time::convertTime(end))
|
||||
);
|
||||
|
||||
LINFO("Preloading: " << _filePath.value());
|
||||
for (const Time& t : preCacheTimes) {
|
||||
getTileProvider(t);
|
||||
}
|
||||
}
|
||||
_successfulInitialization = true;
|
||||
}
|
||||
@@ -102,6 +97,21 @@ TemporalTileProvider::TemporalTileProvider(const ghoul::Dictionary& dictionary)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool TemporalTileProvider::initialize() {
|
||||
bool success = TileProvider::initialize();
|
||||
|
||||
if (!_preCacheTimes.empty()) {
|
||||
LINFO("Preloading: " << _filePath.value());
|
||||
for (const Time& t : _preCacheTimes) {
|
||||
getTileProvider(t);
|
||||
}
|
||||
_preCacheTimes.clear();
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool TemporalTileProvider::readFilePath() {
|
||||
std::ifstream in(_filePath.value().c_str());
|
||||
std::string xml;
|
||||
@@ -295,6 +305,7 @@ std::shared_ptr<TileProvider> TemporalTileProvider::getTileProvider(
|
||||
}
|
||||
else {
|
||||
std::shared_ptr<TileProvider> tileProvider = initTileProvider(timekey);
|
||||
tileProvider->initialize();
|
||||
|
||||
_tileProviderMap[timekey] = tileProvider;
|
||||
return tileProvider;
|
||||
|
||||
@@ -200,6 +200,8 @@ public:
|
||||
*/
|
||||
TemporalTileProvider(const ghoul::Dictionary& dictionary);
|
||||
|
||||
bool initialize() override;
|
||||
|
||||
// These methods implements the TileProvider interface
|
||||
|
||||
virtual Tile getTile(const TileIndex& tileIndex) override;
|
||||
@@ -329,6 +331,9 @@ private:
|
||||
|
||||
TimeFormat* _timeFormat;
|
||||
TimeQuantizer _timeQuantizer;
|
||||
|
||||
std::vector<Time> _preCacheTimes;
|
||||
|
||||
bool _successfulInitialization;
|
||||
};
|
||||
|
||||
|
||||
@@ -47,16 +47,27 @@ TextTileProvider::TextTileProvider(const TileTextureInitData& initData, size_t f
|
||||
, _fontSize(fontSize)
|
||||
{
|
||||
_tileCache = OsEng.moduleEngine().module<GlobeBrowsingModule>()->tileCache();
|
||||
_font = OsEng.fontManager().font("Mono", static_cast<float>(_fontSize));
|
||||
|
||||
_fontRenderer = std::unique_ptr<FontRenderer>(FontRenderer::createDefault());
|
||||
_fontRenderer->setFramebufferSize(glm::vec2(_initData.dimensions()));
|
||||
|
||||
glGenFramebuffers(1, &_fbo);
|
||||
}
|
||||
|
||||
TextTileProvider::~TextTileProvider() {
|
||||
TextTileProvider::~TextTileProvider() {}
|
||||
|
||||
bool TextTileProvider::initialize() {
|
||||
bool res = TileProvider::initialize();
|
||||
|
||||
_font = OsEng.fontManager().font("Mono", static_cast<float>(_fontSize));
|
||||
|
||||
_fontRenderer = std::unique_ptr<FontRenderer>(FontRenderer::createDefault());
|
||||
_fontRenderer->setFramebufferSize(glm::vec2(_initData.dimensions()));
|
||||
|
||||
glGenFramebuffers(1, &_fbo);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool TextTileProvider::deinitialize() {
|
||||
glDeleteFramebuffers(1, &_fbo);
|
||||
|
||||
return TileProvider::deinitialize();
|
||||
}
|
||||
|
||||
Tile TextTileProvider::getTile(const TileIndex& tileIndex) {
|
||||
|
||||
@@ -53,6 +53,9 @@ public:
|
||||
TextTileProvider(const TileTextureInitData& initData, size_t fontSize = 48);
|
||||
virtual ~TextTileProvider() override;
|
||||
|
||||
bool initialize() override;
|
||||
bool deinitialize() override;
|
||||
|
||||
// The TileProvider interface below is implemented in this class
|
||||
virtual Tile getTile(const TileIndex& tileIndex) override;
|
||||
virtual Tile::Status getTileStatus(const TileIndex& index) override;
|
||||
|
||||
@@ -55,17 +55,13 @@ TileProvider::TileProvider()
|
||||
: properties::PropertyOwner({ "tileProvider" })
|
||||
, _initialized(false)
|
||||
, _defaultTile(nullptr, nullptr, Tile::Status::Unavailable)
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
{}
|
||||
|
||||
TileProvider::TileProvider(const ghoul::Dictionary&)
|
||||
: properties::PropertyOwner({ "tileProvider" })
|
||||
, _initialized(false)
|
||||
, _defaultTile(nullptr, nullptr, Tile::Status::Unavailable)
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
{}
|
||||
|
||||
float TileProvider::noDataValueAsFloat() {
|
||||
ghoul_assert(_initialized, "TileProvider was not initialized.");
|
||||
|
||||
@@ -111,6 +111,24 @@ TileProviderByLevel::TileProviderByLevel(const ghoul::Dictionary& dictionary) {
|
||||
}
|
||||
}
|
||||
|
||||
bool TileProviderByLevel::initialize() {
|
||||
bool success = TileProvider::initialize();
|
||||
for (const std::shared_ptr<TileProvider>& tp : _levelTileProviders) {
|
||||
success &= tp->initialize();
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool TileProviderByLevel::deinitialize() {
|
||||
bool success = true;
|
||||
for (const std::shared_ptr<TileProvider>& tp : _levelTileProviders) {
|
||||
success &= tp->deinitialize();
|
||||
}
|
||||
|
||||
return TileProvider::deinitialize() && success;
|
||||
}
|
||||
|
||||
Tile TileProviderByLevel::getTile(const TileIndex& tileIndex) {
|
||||
TileProvider* provider = levelProvider(tileIndex.level);
|
||||
if (provider) {
|
||||
|
||||
@@ -37,6 +37,9 @@ public:
|
||||
TileProviderByLevel(const std::string& imagePath);
|
||||
virtual ~TileProviderByLevel() = default;
|
||||
|
||||
bool initialize() override;
|
||||
bool deinitialize() override;
|
||||
|
||||
virtual Tile getTile(const TileIndex& tileIndex) override;
|
||||
virtual Tile::Status getTileStatus(const TileIndex& index) override;
|
||||
virtual TileDepthTransform depthTransform() override;
|
||||
|
||||
@@ -577,50 +577,61 @@ void OpenSpaceEngine::loadScene(const std::string& scenePath) {
|
||||
}
|
||||
|
||||
Scene* scene;
|
||||
try {
|
||||
scene = _sceneManager->loadScene(scenePath);
|
||||
} catch (const ghoul::FileNotFoundError& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
return;
|
||||
} catch (const Scene::InvalidSceneError& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
return;
|
||||
} catch (const ghoul::RuntimeError& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
return;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
LERROR(e.what());
|
||||
return;
|
||||
}
|
||||
catch (...) {
|
||||
LERROR("Unknown error loading the scene");
|
||||
return;
|
||||
}
|
||||
|
||||
Scene* previousScene = _renderEngine->scene();
|
||||
if (previousScene) {
|
||||
_syncEngine->removeSyncables(_timeManager->getSyncables());
|
||||
_syncEngine->removeSyncables(_renderEngine->getSyncables());
|
||||
_syncEngine->removeSyncable(_scriptEngine.get());
|
||||
|
||||
_renderEngine->setScene(nullptr);
|
||||
_renderEngine->setCamera(nullptr);
|
||||
_sceneManager->unloadScene(*previousScene);
|
||||
}
|
||||
|
||||
// Initialize the RenderEngine
|
||||
_renderEngine->setScene(scene);
|
||||
_renderEngine->setCamera(scene->camera());
|
||||
_renderEngine->setGlobalBlackOutFactor(0.0);
|
||||
_renderEngine->startFading(1, 3.0);
|
||||
|
||||
_loadingScreen = std::make_unique<LoadingScreen>();
|
||||
|
||||
// We can initialize all SceneGraphNodes in a separate thread since none of them use
|
||||
// an OpenGL context
|
||||
std::atomic_bool initializeFinished = false;
|
||||
std::thread t([scene, &initializeFinished, this]() {
|
||||
bool errorWhileLoading = false;
|
||||
std::thread t([&scene, scenePath, &initializeFinished, &errorWhileLoading, this]() {
|
||||
try {
|
||||
scene = _sceneManager->loadScene(scenePath);
|
||||
}
|
||||
catch (const ghoul::FileNotFoundError& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
errorWhileLoading = true;
|
||||
return;
|
||||
}
|
||||
catch (const Scene::InvalidSceneError& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
errorWhileLoading = true;
|
||||
return;
|
||||
}
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
errorWhileLoading = true;
|
||||
return;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
LERROR(e.what());
|
||||
errorWhileLoading = true;
|
||||
return;
|
||||
}
|
||||
catch (...) {
|
||||
LERROR("Unknown error loading the scene");
|
||||
errorWhileLoading = true;
|
||||
return;
|
||||
}
|
||||
|
||||
Scene* previousScene = _renderEngine->scene();
|
||||
if (previousScene) {
|
||||
_syncEngine->removeSyncables(_timeManager->getSyncables());
|
||||
_syncEngine->removeSyncables(_renderEngine->getSyncables());
|
||||
_syncEngine->removeSyncable(_scriptEngine.get());
|
||||
|
||||
_renderEngine->setScene(nullptr);
|
||||
_renderEngine->setCamera(nullptr);
|
||||
_sceneManager->unloadScene(*previousScene);
|
||||
}
|
||||
|
||||
// Initialize the RenderEngine
|
||||
_renderEngine->setScene(scene);
|
||||
_renderEngine->setCamera(scene->camera());
|
||||
_renderEngine->setGlobalBlackOutFactor(0.0);
|
||||
_renderEngine->startFading(1, 3.0);
|
||||
|
||||
scene->initialize();
|
||||
postLoadingScreenMessage("Finished initializing");
|
||||
initializeFinished = true;
|
||||
@@ -638,6 +649,10 @@ void OpenSpaceEngine::loadScene(const std::string& scenePath) {
|
||||
t.join();
|
||||
_loadingScreen = nullptr;
|
||||
|
||||
if (errorWhileLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
scene->initializeGL();
|
||||
|
||||
// Update the scene so that position of objects are set in case they are used in
|
||||
|
||||
Reference in New Issue
Block a user