/***************************************************************************************** * * * OpenSpace * * * * Copyright (c) 2014-2016 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * * without restriction, including without limitation the rights to use, copy, modify, * * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * * permit persons to whom the Software is furnished to do so, subject to the following * * conditions: * * * * The above copyright notice and this permission notice shall be included in all copies * * or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ #include #include #include #include #include #include #include namespace { const std::string _loggerCat = "TileProvider"; } namespace openspace { bool TileProvider::hasInitializedGDAL = false; TileProvider::TileProvider( const std::string& filePath, int tileCacheSize, int minimumPixelSize) : _filePath(filePath) , _tileCache(tileCacheSize) // setting cache size , _minimumPixelSize(minimumPixelSize) { // Set a temporary texture std::string fileName = "textures/earth_bluemarble.jpg"; _defaultTexture = std::move(ghoul::io::TextureReader::ref().loadTexture(absPath(fileName))); if (_defaultTexture) { LDEBUG("Loaded texture from '" << fileName << "'"); _defaultTexture->uploadTexture(); // Textures of planets looks much smoother with AnisotropicMipMap rather than linear // TODO: AnisotropicMipMap crashes on ATI cards ---abock //_testTexture->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap); _defaultTexture->setFilter(ghoul::opengl::Texture::FilterMode::Linear); _defaultTexture->setWrapping(ghoul::opengl::Texture::WrappingMode::ClampToBorder); } int downloadApplicationVersion = 1; if (!DownloadManager::isInitialized()) { DownloadManager::initialize( "../tmp_openspace_downloads/", downloadApplicationVersion); } if (!hasInitializedGDAL) { GDALAllRegister(); hasInitializedGDAL = true; } std::string absFilePath = absPath(filePath); _gdalDataSet = (GDALDataset *)GDALOpen(absFilePath.c_str(), GA_ReadOnly); //auto desc = _gdalDataSet->GetDescription(); ghoul_assert(_gdalDataSet != nullptr, "Failed to load dataset: " << filePath); } TileProvider::~TileProvider(){ delete _gdalDataSet; } void TileProvider::prerender() { while (_tileLoadManager.numFinishedJobs() > 0) { auto finishedJob = _tileLoadManager.popFinishedJob(); std::shared_ptr uninitedTex = finishedJob->product(); HashKey key = uninitedTex->tileIndex.hashKey(); std::shared_ptr texture = initializeTexture(uninitedTex); _tileCache.put(key, texture); } } Tile TileProvider::getMostHiResTile(GeodeticTileIndex tileIndex) { std::shared_ptr tex = nullptr; glm::vec2 uvOffset(0, 0); glm::vec2 uvScale(1, 1); while (true) { tex = getOrStartFetchingTile(tileIndex); if (tex != nullptr) { break; } if (!tileIndex.hasParent()) { tex = getDefaultTexture(); break; } // If we have a parent, calculate the UV offset and scale from the tileIndex else { uvScale *= 0.5; uvOffset *= 0.5; if (tileIndex.isEastChild()) { uvOffset.x += 0.5; } // In OpenGL, positive y direction is up if (tileIndex.isNorthChild()) { uvOffset.y += 0.5; } tileIndex = tileIndex.parent(); } } return { tex, uvOffset, uvScale }; } std::shared_ptr TileProvider::getOrStartFetchingTile(GeodeticTileIndex tileIndex) { HashKey hashkey = tileIndex.hashKey(); if (_tileCache.exist(hashkey)) { return _tileCache.get(hashkey); } else { // enque load job std::shared_ptr job = std::shared_ptr( new TextureTileLoadJob(this, tileIndex)); _tileLoadManager.enqueueJob(job); // map key to nullptr while tile is loaded _tileCache.put(hashkey, nullptr); return nullptr; } } std::shared_ptr TileProvider::getDefaultTexture() { return _defaultTexture; } std::shared_ptr TileProvider::getUninitializedTextureTile( const GeodeticTileIndex& tileIndex) { // We assume here that all rasterbands have the same data type GDALDataType gdalType = _gdalDataSet->GetRasterBand(1)->GetRasterDataType(); switch (gdalType) { case GDT_Byte: return _uByteConverter.getUninitializedTextureTile( _gdalDataSet, tileIndex, _minimumPixelSize); break; case GDT_UInt16: return _uShortConverter.getUninitializedTextureTile( _gdalDataSet, tileIndex, _minimumPixelSize); break; case GDT_Int16: return _shortConverter.getUninitializedTextureTile( _gdalDataSet, tileIndex, _minimumPixelSize); break; case GDT_UInt32: return _uIntConverter.getUninitializedTextureTile( _gdalDataSet, tileIndex, _minimumPixelSize); break; case GDT_Int32: return _intConverter.getUninitializedTextureTile( _gdalDataSet, tileIndex, _minimumPixelSize); break; case GDT_Float32: return _floatConverter.getUninitializedTextureTile( _gdalDataSet, tileIndex, _minimumPixelSize); break; case GDT_Float64: return _doubleConverter.getUninitializedTextureTile( _gdalDataSet, tileIndex, _minimumPixelSize); break; default: LERROR("GDAL data type unknown to OpenGL: " << gdalType); } return nullptr; } std::shared_ptr TileProvider::initializeTexture( std::shared_ptr uninitedTexture) { Texture* tex = new Texture( uninitedTexture->imageData, uninitedTexture->dimensions, uninitedTexture->texFormat.ghoulFormat, uninitedTexture->texFormat.glFormat, uninitedTexture->glType, Texture::FilterMode::Linear, Texture::WrappingMode::ClampToEdge); // The texture should take ownership of the data std::shared_ptr texture = std::shared_ptr(tex); texture->uploadTexture(); return texture; } } // namespace openspace