mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-02-25 06:19:02 -06:00
TileIOResult -> RawTile, PreprocessData -> TileMetaData
This commit is contained in:
@@ -60,7 +60,6 @@ set(HEADER_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/tiledataset.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/tiledatatype.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/tiledepthtransform.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileioresult.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/asynctilereader.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/pixelregion.h
|
||||
|
||||
@@ -111,7 +110,6 @@ set(SOURCE_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/tilediskcache.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/tiledataset.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/tiledatatype.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileioresult.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/asynctilereader.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/pixelregion.cpp
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include <modules/globebrowsing/chunk/chunk.h>
|
||||
#include <modules/globebrowsing/globes/renderableglobe.h>
|
||||
#include <modules/globebrowsing/globes/chunkedlodglobe.h>
|
||||
#include <modules/globebrowsing/tile/tileioresult.h>
|
||||
#include <modules/globebrowsing/tile/tile.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -109,36 +109,36 @@ namespace globebrowsing {
|
||||
size_t HEIGHT_CHANNEL = 0;
|
||||
const LayerGroup& heightmaps =
|
||||
layerManager->layerGroup(LayerManager::HeightLayers);
|
||||
std::vector<ChunkTile> tiles =
|
||||
std::vector<ChunkTile> chunkTiles =
|
||||
TileSelector::getTilesSortedByHighestResolution(heightmaps, _tileIndex);
|
||||
bool lastHadMissingData = true;
|
||||
for (auto tile : tiles) {
|
||||
bool goodTile = tile.tile.status == Tile::Status::OK;
|
||||
bool hasPreprocessData = tile.tile.preprocessData != nullptr;
|
||||
for (auto chunkTile : chunkTiles) {
|
||||
bool goodTile = chunkTile.tile.status == Tile::Status::OK;
|
||||
bool hastileMetaData = chunkTile.tile.metaData != nullptr;
|
||||
|
||||
if (goodTile && hasPreprocessData) {
|
||||
auto preprocessData = tile.tile.preprocessData;
|
||||
if (goodTile && hastileMetaData) {
|
||||
auto tileMetaData = chunkTile.tile.metaData;
|
||||
|
||||
if (!boundingHeights.available) {
|
||||
if (preprocessData->hasMissingData[HEIGHT_CHANNEL]) {
|
||||
if (tileMetaData->hasMissingData[HEIGHT_CHANNEL]) {
|
||||
boundingHeights.min = std::min(
|
||||
DEFAULT_HEIGHT, preprocessData->minValues[HEIGHT_CHANNEL]);
|
||||
DEFAULT_HEIGHT, tileMetaData->minValues[HEIGHT_CHANNEL]);
|
||||
boundingHeights.max = std::max(
|
||||
DEFAULT_HEIGHT, preprocessData->maxValues[HEIGHT_CHANNEL]);
|
||||
DEFAULT_HEIGHT, tileMetaData->maxValues[HEIGHT_CHANNEL]);
|
||||
}
|
||||
else {
|
||||
boundingHeights.min = preprocessData->minValues[HEIGHT_CHANNEL];
|
||||
boundingHeights.max = preprocessData->maxValues[HEIGHT_CHANNEL];
|
||||
boundingHeights.min = tileMetaData->minValues[HEIGHT_CHANNEL];
|
||||
boundingHeights.max = tileMetaData->maxValues[HEIGHT_CHANNEL];
|
||||
}
|
||||
boundingHeights.available = true;
|
||||
}
|
||||
else {
|
||||
boundingHeights.min = std::min(
|
||||
boundingHeights.min, preprocessData->minValues[HEIGHT_CHANNEL]);
|
||||
boundingHeights.min, tileMetaData->minValues[HEIGHT_CHANNEL]);
|
||||
boundingHeights.max = std::max(
|
||||
boundingHeights.max, preprocessData->maxValues[HEIGHT_CHANNEL]);
|
||||
boundingHeights.max, tileMetaData->maxValues[HEIGHT_CHANNEL]);
|
||||
}
|
||||
lastHadMissingData = preprocessData->hasMissingData[HEIGHT_CHANNEL];
|
||||
lastHadMissingData = tileMetaData->hasMissingData[HEIGHT_CHANNEL];
|
||||
}
|
||||
|
||||
// Allow for early termination
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace globebrowsing {
|
||||
: _cacheSize(size) { }
|
||||
|
||||
template<typename KeyType, typename ValueType>
|
||||
LRUCache<KeyType, ValueType>::~LRUCache() {
|
||||
LRUCache<KeyType, ValueType>::~LRUCache() {
|
||||
// Clean up list and map!
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace openspace {
|
||||
namespace globebrowsing {
|
||||
|
||||
void TileLoadJob::execute() {
|
||||
_tileIOResult = _tileDataset->readTileData(_chunkIndex);
|
||||
_rawTile = _tileDataset->readTileData(_chunkIndex);
|
||||
}
|
||||
|
||||
DiskCachedTileLoadJob::DiskCachedTileLoadJob(std::shared_ptr<TileDataset> textureDataProvider,
|
||||
@@ -65,39 +65,39 @@ namespace globebrowsing {
|
||||
}
|
||||
|
||||
void DiskCachedTileLoadJob::execute() {
|
||||
_tileIOResult = nullptr;
|
||||
_rawTile = nullptr;
|
||||
|
||||
switch (_mode) {
|
||||
case CacheMode::Disabled:
|
||||
_tileIOResult = _tileDataset->readTileData(_chunkIndex);
|
||||
_rawTile = _tileDataset->readTileData(_chunkIndex);
|
||||
break;
|
||||
|
||||
case CacheMode::ReadOnly:
|
||||
_tileIOResult = _tileDiskCache->get(_chunkIndex);
|
||||
if (_tileIOResult == nullptr) {
|
||||
_tileIOResult = _tileDataset->readTileData(_chunkIndex);
|
||||
_rawTile = _tileDiskCache->get(_chunkIndex);
|
||||
if (_rawTile == nullptr) {
|
||||
_rawTile = _tileDataset->readTileData(_chunkIndex);
|
||||
}
|
||||
break;
|
||||
|
||||
case CacheMode::ReadAndWrite:
|
||||
_tileIOResult = _tileDiskCache->get(_chunkIndex);
|
||||
if (_tileIOResult == nullptr) {
|
||||
_tileIOResult = _tileDataset->readTileData(_chunkIndex);
|
||||
_tileDiskCache->put(_chunkIndex, _tileIOResult);
|
||||
_rawTile = _tileDiskCache->get(_chunkIndex);
|
||||
if (_rawTile == nullptr) {
|
||||
_rawTile = _tileDataset->readTileData(_chunkIndex);
|
||||
_tileDiskCache->put(_chunkIndex, _rawTile);
|
||||
}
|
||||
break;
|
||||
|
||||
case CacheMode::WriteOnly:
|
||||
_tileIOResult = _tileDataset->readTileData(_chunkIndex);
|
||||
_tileDiskCache->put(_chunkIndex, _tileIOResult);
|
||||
_rawTile = _tileDataset->readTileData(_chunkIndex);
|
||||
_tileDiskCache->put(_chunkIndex, _rawTile);
|
||||
break;
|
||||
|
||||
case CacheMode::CacheHitsOnly:
|
||||
_tileIOResult = _tileDiskCache->get(_chunkIndex);
|
||||
if (_tileIOResult == nullptr) {
|
||||
TileIOResult res = TileIOResult::createDefaultRes();
|
||||
_rawTile = _tileDiskCache->get(_chunkIndex);
|
||||
if (_rawTile == nullptr) {
|
||||
RawTile res = RawTile::createDefaultRes();
|
||||
res.tileIndex = _chunkIndex;
|
||||
_tileIOResult = std::make_shared<TileIOResult>(res);
|
||||
_rawTile = std::make_shared<RawTile>(res);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -129,8 +129,8 @@ namespace globebrowsing {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<TileIOResult>> AsyncTileDataProvider::getTileIOResults() {
|
||||
std::vector<std::shared_ptr<TileIOResult>> readyResults;
|
||||
std::vector<std::shared_ptr<RawTile>> AsyncTileDataProvider::getRawTiles() {
|
||||
std::vector<std::shared_ptr<RawTile>> readyResults;
|
||||
while (_concurrentJobManager.numFinishedJobs() > 0) {
|
||||
readyResults.push_back(_concurrentJobManager.popFinishedJob()->product());
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include <ghoul/opengl/texture.h>
|
||||
|
||||
#include <modules/globebrowsing/geometry/geodetic2.h>
|
||||
|
||||
#include <modules/globebrowsing/tile/tile.h>
|
||||
#include <modules/globebrowsing/other/concurrentjobmanager.h>
|
||||
#include <modules/globebrowsing/other/threadpool.h>
|
||||
//#include <ghoul/misc/threadpool.h>
|
||||
@@ -46,9 +46,9 @@
|
||||
namespace openspace {
|
||||
namespace globebrowsing {
|
||||
|
||||
struct LoadJob : public Job<TileIOResult> {
|
||||
struct LoadJob : public Job<RawTile> {
|
||||
virtual void execute() = 0;
|
||||
virtual std::shared_ptr<TileIOResult> product() = 0;
|
||||
virtual std::shared_ptr<RawTile> product() = 0;
|
||||
};
|
||||
|
||||
struct TileLoadJob : LoadJob {
|
||||
@@ -62,14 +62,14 @@ namespace globebrowsing {
|
||||
|
||||
virtual void execute();
|
||||
|
||||
virtual std::shared_ptr<TileIOResult> product() {
|
||||
return _tileIOResult;
|
||||
virtual std::shared_ptr<RawTile> product() {
|
||||
return _rawTile;
|
||||
}
|
||||
|
||||
protected:
|
||||
TileIndex _chunkIndex;
|
||||
std::shared_ptr<TileDataset> _tileDataset;
|
||||
std::shared_ptr<TileIOResult> _tileIOResult;
|
||||
std::shared_ptr<RawTile> _rawTile;
|
||||
};
|
||||
|
||||
class TileDiskCache;
|
||||
@@ -107,7 +107,7 @@ namespace globebrowsing {
|
||||
~AsyncTileDataProvider();
|
||||
|
||||
bool enqueueTileIO(const TileIndex& tileIndex);
|
||||
std::vector<std::shared_ptr<TileIOResult>> getTileIOResults();
|
||||
std::vector<std::shared_ptr<RawTile>> getRawTiles();
|
||||
|
||||
void reset();
|
||||
void clearRequestQueue();
|
||||
@@ -120,7 +120,7 @@ namespace globebrowsing {
|
||||
|
||||
private:
|
||||
std::shared_ptr<TileDataset> _tileDataset;
|
||||
ConcurrentJobManager<TileIOResult> _concurrentJobManager;
|
||||
ConcurrentJobManager<RawTile> _concurrentJobManager;
|
||||
std::unordered_map<TileHashKey, TileIndex> _enqueuedTileRequests;
|
||||
};
|
||||
|
||||
@@ -131,4 +131,4 @@ namespace globebrowsing {
|
||||
|
||||
|
||||
|
||||
#endif // __ASYNC_TILE_DATA_PROVIDER_H__
|
||||
#endif // __ASYNC_TILE_DATA_PROVIDER_H__
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/globebrowsing/tile/tile.h>
|
||||
#include <modules/globebrowsing/tile/tiledataset.h>
|
||||
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
|
||||
@@ -33,6 +33,93 @@ namespace {
|
||||
namespace openspace {
|
||||
namespace globebrowsing {
|
||||
|
||||
|
||||
|
||||
void TileMetaData::serialize(std::ostream& os) {
|
||||
os << maxValues.size() << std::endl;
|
||||
for (float f : maxValues) {
|
||||
os << f << " ";
|
||||
}
|
||||
os << std::endl;
|
||||
for (float f : minValues) {
|
||||
os << f << " ";
|
||||
}
|
||||
os << std::endl;
|
||||
}
|
||||
|
||||
TileMetaData TileMetaData::deserialize(std::istream& is) {
|
||||
TileMetaData res;
|
||||
int n; is >> n;
|
||||
res.maxValues.resize(n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
is >> res.maxValues[i];
|
||||
}
|
||||
res.minValues.resize(n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
is >> res.minValues[i];
|
||||
}
|
||||
|
||||
return std::move(res);
|
||||
}
|
||||
|
||||
RawTile::RawTile()
|
||||
: imageData(nullptr)
|
||||
, dimensions(0, 0, 0)
|
||||
, tileMetaData(nullptr)
|
||||
, tileIndex(0, 0, 0)
|
||||
, error(CE_None)
|
||||
, nBytesImageData(0)
|
||||
{}
|
||||
|
||||
RawTile RawTile::createDefaultRes() {
|
||||
RawTile defaultRes;
|
||||
int w = 8;
|
||||
int h = 8;
|
||||
defaultRes.dimensions = glm::uvec3(w, h, 1);
|
||||
defaultRes.nBytesImageData = w * h * 1 * 3 * 4; // assume max 3 channels, max 4 bytes per pixel
|
||||
defaultRes.imageData = new char[defaultRes.nBytesImageData];
|
||||
std::fill_n((char*)defaultRes.imageData, defaultRes.nBytesImageData, 0);
|
||||
return std::move(defaultRes);
|
||||
}
|
||||
|
||||
void RawTile::serializeMetaData(std::ostream& os) {
|
||||
os << dimensions.x << " " << dimensions.y << " " << dimensions.z << std::endl;
|
||||
os << tileIndex.x << " " << tileIndex.y << " " << tileIndex.level << std::endl;
|
||||
os << error << std::endl;
|
||||
|
||||
// preprocess data
|
||||
os << (tileMetaData != nullptr) << std::endl;
|
||||
if (tileMetaData != nullptr) {
|
||||
tileMetaData->serialize(os);
|
||||
}
|
||||
|
||||
os << nBytesImageData << std::endl;
|
||||
}
|
||||
|
||||
RawTile RawTile::deserializeMetaData(std::istream& is) {
|
||||
RawTile res;
|
||||
is >> res.dimensions.x >> res.dimensions.y >> res.dimensions.z;
|
||||
is >> res.tileIndex.x >> res.tileIndex.y >> res.tileIndex.level;
|
||||
int err; is >> err; res.error = (CPLErr) err;
|
||||
|
||||
res.tileMetaData = nullptr;
|
||||
bool hastileMetaData;
|
||||
is >> hastileMetaData;
|
||||
if (hastileMetaData) {
|
||||
TileMetaData tileMetaData = TileMetaData::deserialize(is);
|
||||
res.tileMetaData = std::make_shared<TileMetaData>(tileMetaData);
|
||||
}
|
||||
|
||||
is >> res.nBytesImageData;
|
||||
|
||||
char binaryDataSeparator;
|
||||
is >> binaryDataSeparator; // not used
|
||||
|
||||
char* buffer = new char[res.nBytesImageData]();
|
||||
return std::move(res);
|
||||
}
|
||||
|
||||
|
||||
const Tile Tile::TileUnavailable = {nullptr, nullptr, Tile::Status::Unavailable };
|
||||
|
||||
Tile Tile::createPlainTile(const glm::uvec2& size, const glm::uvec4& color) {
|
||||
@@ -60,7 +147,7 @@ namespace globebrowsing {
|
||||
// Create tile
|
||||
Tile tile;
|
||||
tile.status = Tile::Status::OK;
|
||||
tile.preprocessData = nullptr;
|
||||
tile.metaData = nullptr;
|
||||
tile.texture = texture;
|
||||
|
||||
return tile;
|
||||
|
||||
@@ -27,24 +27,60 @@
|
||||
|
||||
#include <ghoul/opengl/texture.h> // Texture
|
||||
|
||||
#include <modules/globebrowsing/tile/asynctilereader.h> // TilePreprocessData
|
||||
#include <modules/globebrowsing/tile/tileindex.h>
|
||||
#include <gdal_priv.h>
|
||||
|
||||
namespace openspace {
|
||||
namespace globebrowsing {
|
||||
|
||||
|
||||
struct TileMetaData {
|
||||
std::vector<float> maxValues;
|
||||
std::vector<float> minValues;
|
||||
std::vector<bool> hasMissingData;
|
||||
|
||||
void serialize(std::ostream& s);
|
||||
static TileMetaData deserialize(std::istream& s);
|
||||
};
|
||||
|
||||
struct TextureFormat {
|
||||
ghoul::opengl::Texture::Format ghoulFormat;
|
||||
GLuint glFormat;
|
||||
};
|
||||
|
||||
using namespace ghoul::opengl;
|
||||
|
||||
struct RawTile {
|
||||
RawTile();
|
||||
|
||||
char* imageData;
|
||||
glm::uvec3 dimensions;
|
||||
std::shared_ptr<TileMetaData> tileMetaData;
|
||||
TileIndex tileIndex;
|
||||
CPLErr error;
|
||||
size_t nBytesImageData;
|
||||
|
||||
void serializeMetaData(std::ostream& s);
|
||||
static RawTile deserializeMetaData(std::istream& s);
|
||||
|
||||
static RawTile createDefaultRes();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct TileUvTransform {
|
||||
glm::vec2 uvOffset;
|
||||
glm::vec2 uvScale;
|
||||
};
|
||||
|
||||
using namespace ghoul::opengl;
|
||||
|
||||
/**
|
||||
* Defines a status and may have a Texture and PreprocessData
|
||||
* Defines a status and may have a Texture and TileMetaData
|
||||
*/
|
||||
struct Tile {
|
||||
std::shared_ptr<Texture> texture;
|
||||
std::shared_ptr<TilePreprocessData> preprocessData;
|
||||
std::shared_ptr<TileMetaData> metaData;
|
||||
|
||||
/**
|
||||
* Describe if this Tile is good for usage (OK) or otherwise
|
||||
@@ -53,7 +89,7 @@ namespace globebrowsing {
|
||||
enum class Status {
|
||||
/**
|
||||
* E.g when texture data is not currently in memory.
|
||||
* texture and preprocessData are both null
|
||||
* texture and tileMetaData are both null
|
||||
*/
|
||||
Unavailable,
|
||||
|
||||
@@ -61,19 +97,19 @@ namespace globebrowsing {
|
||||
* Can be set by <code>TileProvider</code>s if the requested
|
||||
* <code>TileIndex</code> is undefined for that particular
|
||||
* provider.
|
||||
* texture and preprocessData are both null
|
||||
* texture and metaData are both null
|
||||
*/
|
||||
OutOfRange,
|
||||
|
||||
/**
|
||||
* An IO Error happend
|
||||
* texture and preprocessData are both null
|
||||
* texture and metaData are both null
|
||||
*/
|
||||
IOError,
|
||||
|
||||
/**
|
||||
* The Texture is uploaded to the GPU and good for usage.
|
||||
* texture is defined. preprocessData may be defined.
|
||||
* texture is defined. metaData may be defined.
|
||||
*/
|
||||
OK
|
||||
} status;
|
||||
@@ -112,4 +148,4 @@ namespace globebrowsing {
|
||||
} // namespace openspace
|
||||
|
||||
|
||||
#endif // __TILE_H__
|
||||
#endif // __TILE_H__
|
||||
|
||||
@@ -31,14 +31,14 @@
|
||||
#include <ghoul/filesystem/filesystem.h> // abspath
|
||||
#include <ghoul/misc/assert.h>
|
||||
|
||||
#include <modules/globebrowsing/tile/tile.h>
|
||||
#include <modules/globebrowsing/tile/tiledataset.h>
|
||||
#include <modules/globebrowsing/tile/tileprovider/tileprovider.h>
|
||||
#include <modules/globebrowsing/tile/tileioresult.h>
|
||||
|
||||
|
||||
#include <modules/globebrowsing/geometry/angle.h>
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
@@ -266,47 +266,47 @@ namespace globebrowsing {
|
||||
// Public interface //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::shared_ptr<TileIOResult> TileDataset::readTileData(TileIndex tileIndex) {
|
||||
std::shared_ptr<RawTile> TileDataset::readTileData(TileIndex tileIndex) {
|
||||
ensureInitialized();
|
||||
IODescription io = getIODescription(tileIndex);
|
||||
CPLErr worstError = CPLErr::CE_None;
|
||||
|
||||
// Build the Tile IO Result from the data we queride
|
||||
std::shared_ptr<TileIOResult> result = std::make_shared<TileIOResult>();
|
||||
result->imageData = readImageData(io, worstError);
|
||||
result->error = worstError;
|
||||
result->tileIndex = tileIndex;
|
||||
result->dimensions = glm::uvec3(io.write.region.numPixels, 1);
|
||||
result->nBytesImageData = io.write.totalNumBytes;
|
||||
// Build the RawTile from the data we querred
|
||||
std::shared_ptr<RawTile> rawTile = std::make_shared<RawTile>();
|
||||
rawTile->imageData = readImageData(io, worstError);
|
||||
rawTile->error = worstError;
|
||||
rawTile->tileIndex = tileIndex;
|
||||
rawTile->dimensions = glm::uvec3(io.write.region.numPixels, 1);
|
||||
rawTile->nBytesImageData = io.write.totalNumBytes;
|
||||
|
||||
if (_config.doPreProcessing) {
|
||||
result->preprocessData = preprocess(result, io.write.region);
|
||||
result->error = std::max(result->error, postProcessErrorCheck(result, io));
|
||||
rawTile->tileMetaData = getTileMetaData(rawTile, io.write.region);
|
||||
rawTile->error = std::max(rawTile->error, postProcessErrorCheck(rawTile, io));
|
||||
}
|
||||
|
||||
return result;
|
||||
return rawTile;
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<TileIOResult> TileDataset::defaultTileData() {
|
||||
std::shared_ptr<RawTile> TileDataset::defaultTileData() {
|
||||
ensureInitialized();
|
||||
PixelRegion pixelRegion = { PixelCoordinate(0, 0), PixelRange(16, 16) };
|
||||
std::shared_ptr<TileIOResult> result = std::make_shared<TileIOResult>();
|
||||
result->tileIndex = { 0, 0, 0 };
|
||||
result->dimensions = glm::uvec3(pixelRegion.numPixels, 1);
|
||||
result->nBytesImageData = result->dimensions.x * result->dimensions.y * _dataLayout.bytesPerPixel;
|
||||
result->imageData = new char[result->nBytesImageData];
|
||||
for (size_t i = 0; i < result->nBytesImageData; ++i) {
|
||||
result->imageData[i] = 0;
|
||||
std::shared_ptr<RawTile> rawTile = std::make_shared<RawTile>();
|
||||
rawTile->tileIndex = { 0, 0, 0 };
|
||||
rawTile->dimensions = glm::uvec3(pixelRegion.numPixels, 1);
|
||||
rawTile->nBytesImageData = rawTile->dimensions.x * rawTile->dimensions.y * _dataLayout.bytesPerPixel;
|
||||
rawTile->imageData = new char[rawTile->nBytesImageData];
|
||||
for (size_t i = 0; i < rawTile->nBytesImageData; ++i) {
|
||||
rawTile->imageData[i] = 0;
|
||||
}
|
||||
result->error = CPLErr::CE_None;
|
||||
rawTile->error = CPLErr::CE_None;
|
||||
|
||||
if (_config.doPreProcessing) {
|
||||
result->preprocessData = preprocess(result, pixelRegion);
|
||||
//result->error = std::max(result->error, postProcessErrorCheck(result, io));
|
||||
rawTile->tileMetaData = getTileMetaData(rawTile, pixelRegion);
|
||||
//rawTile->error = std::max(rawTile->error, postProcessErrorCheck(rawTile, io));
|
||||
}
|
||||
|
||||
return result;
|
||||
return rawTile;
|
||||
}
|
||||
|
||||
int TileDataset::maxChunkLevel() {
|
||||
@@ -726,11 +726,11 @@ namespace globebrowsing {
|
||||
-io.write.bytesPerLine); // Line spacing
|
||||
}
|
||||
|
||||
std::shared_ptr<TilePreprocessData> TileDataset::preprocess(std::shared_ptr<TileIOResult> result, const PixelRegion& region) const {
|
||||
std::shared_ptr<TileMetaData> TileDataset::getTileMetaData(std::shared_ptr<RawTile> rawTile, const PixelRegion& region) const {
|
||||
size_t bytesPerLine = _dataLayout.bytesPerPixel * region.numPixels.x;
|
||||
size_t totalNumBytes = bytesPerLine * region.numPixels.y;
|
||||
|
||||
TilePreprocessData* preprocessData = new TilePreprocessData();
|
||||
TileMetaData* preprocessData = new TileMetaData();
|
||||
preprocessData->maxValues.resize(_dataLayout.numRasters);
|
||||
preprocessData->minValues.resize(_dataLayout.numRasters);
|
||||
preprocessData->hasMissingData.resize(_dataLayout.numRasters);
|
||||
@@ -752,7 +752,7 @@ namespace globebrowsing {
|
||||
|
||||
for (size_t c = 0; c < _dataLayout.numRasters; c++) {
|
||||
float noDataValue = _dataset->GetRasterBand(c + 1)->GetNoDataValue();
|
||||
float val = TileDataType::interpretFloat(_dataLayout.gdalType, &(result->imageData[yi + i]));
|
||||
float val = TileDataType::interpretFloat(_dataLayout.gdalType, &(rawTile->imageData[yi + i]));
|
||||
if (val != noDataValue) {
|
||||
preprocessData->maxValues[c] = std::max(val, preprocessData->maxValues[c]);
|
||||
preprocessData->minValues[c] = std::min(val, preprocessData->minValues[c]);
|
||||
@@ -771,10 +771,10 @@ namespace globebrowsing {
|
||||
}
|
||||
}
|
||||
|
||||
return std::shared_ptr<TilePreprocessData>(preprocessData);
|
||||
return std::shared_ptr<TileMetaData>(preprocessData);
|
||||
}
|
||||
|
||||
CPLErr TileDataset::postProcessErrorCheck(std::shared_ptr<const TileIOResult> result, const IODescription& io) const{
|
||||
CPLErr TileDataset::postProcessErrorCheck(std::shared_ptr<const RawTile> rawTile, const IODescription& io) const{
|
||||
int success;
|
||||
|
||||
double missingDataValue = gdalRasterBand(io.read.overview)->GetNoDataValue(&success);
|
||||
@@ -785,18 +785,18 @@ namespace globebrowsing {
|
||||
bool hasMissingData = false;
|
||||
|
||||
for (size_t c = 0; c < _dataLayout.numRasters; c++) {
|
||||
hasMissingData |= result->preprocessData->maxValues[c] == missingDataValue;
|
||||
hasMissingData |= rawTile->tileMetaData->maxValues[c] == missingDataValue;
|
||||
}
|
||||
|
||||
bool onHighLevel = result->tileIndex.level > 6;
|
||||
bool onHighLevel = rawTile->tileIndex.level > 6;
|
||||
if (hasMissingData && onHighLevel) {
|
||||
return CE_Fatal;
|
||||
}
|
||||
// ugly test for heightmap overlay
|
||||
if (_dataLayout.textureFormat.ghoulFormat == Texture::Format::RG) {
|
||||
// check the alpha
|
||||
if (result->preprocessData->maxValues[1] == 0.0
|
||||
&& result->preprocessData->minValues[1] == 0.0)
|
||||
if (rawTile->tileMetaData->maxValues[1] == 0.0
|
||||
&& rawTile->tileMetaData->minValues[1] == 0.0)
|
||||
{
|
||||
//return CE_Warning;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,9 @@
|
||||
#include <ghoul/opengl/texture.h>
|
||||
#include <ghoul/misc/threadpool.h>
|
||||
|
||||
#include <modules/globebrowsing/tile/tile.h>
|
||||
#include <modules/globebrowsing/tile/tiledatatype.h>
|
||||
#include <modules/globebrowsing/tile/tiledepthtransform.h>
|
||||
#include <modules/globebrowsing/tile/pixelregion.h>
|
||||
#include <modules/globebrowsing/geometry/geodetic2.h>
|
||||
|
||||
@@ -101,8 +103,8 @@ namespace globebrowsing {
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Public interface //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
std::shared_ptr<TileIOResult> readTileData(TileIndex tileIndex);
|
||||
std::shared_ptr<TileIOResult> defaultTileData();
|
||||
std::shared_ptr<RawTile> readTileData(TileIndex tileIndex);
|
||||
std::shared_ptr<RawTile> defaultTileData();
|
||||
int maxChunkLevel();
|
||||
TileDepthTransform getDepthTransform();
|
||||
const TileDataLayout& getDataLayout();
|
||||
@@ -162,8 +164,8 @@ namespace globebrowsing {
|
||||
char* readImageData(IODescription& io, CPLErr& worstError) const;
|
||||
CPLErr rasterIO(GDALRasterBand* rasterBand, const IODescription& io, char* dst) const;
|
||||
CPLErr repeatedRasterIO(GDALRasterBand* rasterBand, const IODescription& io, char* dst, int depth = 0) const;
|
||||
std::shared_ptr<TilePreprocessData> preprocess(std::shared_ptr<TileIOResult> result, const PixelRegion& region) const;
|
||||
CPLErr postProcessErrorCheck(std::shared_ptr<const TileIOResult> ioResult, const IODescription& io) const;
|
||||
std::shared_ptr<TileMetaData> getTileMetaData(std::shared_ptr<RawTile> result, const PixelRegion& region) const;
|
||||
CPLErr postProcessErrorCheck(std::shared_ptr<const RawTile> ioResult, const IODescription& io) const;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "TileIOResult";
|
||||
const std::string _loggerCat = "RawTile";
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <ghoul/opengl/texture.h>
|
||||
|
||||
#include <modules/globebrowsing/geometry/geodetic2.h>
|
||||
#include <modules/globebrowsing/tile/tileioresult.h>
|
||||
#include <modules/globebrowsing/tile/tile.h>
|
||||
|
||||
#include "gdal_priv.h"
|
||||
|
||||
|
||||
@@ -23,8 +23,7 @@
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/globebrowsing/tile/tilediskcache.h>
|
||||
|
||||
#include <modules/globebrowsing/tile/tileioresult.h>
|
||||
#include <modules/globebrowsing/tile/tile.h>
|
||||
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
|
||||
@@ -61,14 +60,14 @@ namespace globebrowsing {
|
||||
return FileSys.fileExists(metaFile);
|
||||
}
|
||||
|
||||
std::shared_ptr<TileIOResult> TileDiskCache::get(const TileIndex& tileIndex) {
|
||||
std::shared_ptr<RawTile> TileDiskCache::get(const TileIndex& tileIndex) {
|
||||
File metaDataFile = getMetaDataFile(tileIndex);
|
||||
File dataFile = getDataFile(tileIndex);
|
||||
if (FileSys.fileExists(metaDataFile) && FileSys.fileExists(dataFile)) {
|
||||
// read meta
|
||||
std::ifstream ifsMeta;
|
||||
ifsMeta.open(metaDataFile.path(), std::ifstream::in);
|
||||
TileIOResult res = TileIOResult::deserializeMetaData(ifsMeta);
|
||||
RawTile res = RawTile::deserializeMetaData(ifsMeta);
|
||||
ifsMeta.close();
|
||||
|
||||
// read data
|
||||
@@ -78,24 +77,24 @@ namespace globebrowsing {
|
||||
ifsData.read(buffer, res.nBytesImageData);
|
||||
res.imageData = buffer;
|
||||
|
||||
return std::make_shared<TileIOResult>(res);
|
||||
return std::make_shared<RawTile>(res);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool TileDiskCache::put(const TileIndex& tileIndex, std::shared_ptr<TileIOResult> tileIOResult) {
|
||||
bool TileDiskCache::put(const TileIndex& tileIndex, std::shared_ptr<RawTile> rawTile) {
|
||||
File metaDataFile = getMetaDataFile(tileIndex);
|
||||
if (!FileSys.fileExists(metaDataFile)) {
|
||||
std::ofstream ofsMeta;
|
||||
ofsMeta.open(metaDataFile.path());
|
||||
tileIOResult->serializeMetaData(ofsMeta);
|
||||
rawTile->serializeMetaData(ofsMeta);
|
||||
ofsMeta.close();
|
||||
|
||||
std::ofstream ofsData;
|
||||
File dataFile = getDataFile(tileIndex);
|
||||
ofsData.open(dataFile.path(), std::ofstream::binary);
|
||||
char * data = (char*)tileIOResult->imageData;
|
||||
ofsData.write(data, tileIOResult->nBytesImageData);
|
||||
char * data = (char*)rawTile->imageData;
|
||||
ofsData.write(data, rawTile->nBytesImageData);
|
||||
ofsData.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
namespace openspace {
|
||||
namespace globebrowsing {
|
||||
|
||||
struct TileIOResult;
|
||||
struct RawTile;
|
||||
|
||||
using namespace ghoul::filesystem;
|
||||
|
||||
@@ -41,9 +41,9 @@ struct TileIOResult;
|
||||
public:
|
||||
TileDiskCache(const std::string& name);
|
||||
|
||||
std::shared_ptr<TileIOResult> get(const TileIndex& tileIndex);
|
||||
std::shared_ptr<RawTile> get(const TileIndex& tileIndex);
|
||||
bool has(const TileIndex& tileIndex) const;
|
||||
bool put(const TileIndex& tileIndex, std::shared_ptr<TileIOResult> tileIOResult);
|
||||
bool put(const TileIndex& tileIndex, std::shared_ptr<RawTile> rawTile);
|
||||
|
||||
static const std::string CACHE_ROOT;
|
||||
|
||||
|
||||
@@ -29,8 +29,7 @@
|
||||
#include <ghoul/filesystem/filesystem.h> // abspath
|
||||
#include <ghoul/misc/assert.h>
|
||||
|
||||
#include <modules/globebrowsing/tile/tileioresult.h>
|
||||
|
||||
#include <modules/globebrowsing/tile/tile.h>
|
||||
#include <modules/globebrowsing/geometry/angle.h>
|
||||
|
||||
#include <float.h>
|
||||
@@ -39,94 +38,12 @@
|
||||
#include <algorithm>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "TileIOResult";
|
||||
const std::string _loggerCat = "RawTile";
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
namespace globebrowsing {
|
||||
void TilePreprocessData::serialize(std::ostream& os) {
|
||||
os << maxValues.size() << std::endl;
|
||||
for (float f : maxValues) {
|
||||
os << f << " ";
|
||||
}
|
||||
os << std::endl;
|
||||
for (float f : minValues) {
|
||||
os << f << " ";
|
||||
}
|
||||
os << std::endl;
|
||||
}
|
||||
|
||||
TilePreprocessData TilePreprocessData::deserialize(std::istream& is) {
|
||||
TilePreprocessData res;
|
||||
int n; is >> n;
|
||||
res.maxValues.resize(n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
is >> res.maxValues[i];
|
||||
}
|
||||
res.minValues.resize(n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
is >> res.minValues[i];
|
||||
}
|
||||
|
||||
return std::move(res);
|
||||
}
|
||||
|
||||
TileIOResult::TileIOResult()
|
||||
: imageData(nullptr)
|
||||
, dimensions(0, 0, 0)
|
||||
, preprocessData(nullptr)
|
||||
, tileIndex(0, 0, 0)
|
||||
, error(CE_None)
|
||||
, nBytesImageData(0)
|
||||
{}
|
||||
|
||||
TileIOResult TileIOResult::createDefaultRes() {
|
||||
TileIOResult defaultRes;
|
||||
int w = 8;
|
||||
int h = 8;
|
||||
defaultRes.dimensions = glm::uvec3(w, h, 1);
|
||||
defaultRes.nBytesImageData = w * h * 1 * 3 * 4; // assume max 3 channels, max 4 bytes per pixel
|
||||
defaultRes.imageData = new char[defaultRes.nBytesImageData];
|
||||
std::fill_n((char*)defaultRes.imageData, defaultRes.nBytesImageData, 0);
|
||||
return std::move(defaultRes);
|
||||
}
|
||||
|
||||
void TileIOResult::serializeMetaData(std::ostream& os) {
|
||||
os << dimensions.x << " " << dimensions.y << " " << dimensions.z << std::endl;
|
||||
os << tileIndex.x << " " << tileIndex.y << " " << tileIndex.level << std::endl;
|
||||
os << error << std::endl;
|
||||
|
||||
// preprocess data
|
||||
os << (preprocessData != nullptr) << std::endl;
|
||||
if (preprocessData != nullptr) {
|
||||
preprocessData->serialize(os);
|
||||
}
|
||||
|
||||
os << nBytesImageData << std::endl;
|
||||
}
|
||||
|
||||
TileIOResult TileIOResult::deserializeMetaData(std::istream& is) {
|
||||
TileIOResult res;
|
||||
is >> res.dimensions.x >> res.dimensions.y >> res.dimensions.z;
|
||||
is >> res.tileIndex.x >> res.tileIndex.y >> res.tileIndex.level;
|
||||
int err; is >> err; res.error = (CPLErr) err;
|
||||
|
||||
res.preprocessData = nullptr;
|
||||
bool hasPreprocessData;
|
||||
is >> hasPreprocessData;
|
||||
if (hasPreprocessData) {
|
||||
TilePreprocessData preprocessData = TilePreprocessData::deserialize(is);
|
||||
res.preprocessData = std::make_shared<TilePreprocessData>(preprocessData);
|
||||
}
|
||||
|
||||
is >> res.nBytesImageData;
|
||||
|
||||
char binaryDataSeparator;
|
||||
is >> binaryDataSeparator; // not used
|
||||
|
||||
char* buffer = new char[res.nBytesImageData]();
|
||||
return std::move(res);
|
||||
}
|
||||
|
||||
|
||||
} // namespace globebrowsing
|
||||
} // namespace openspace
|
||||
|
||||
@@ -26,10 +26,9 @@
|
||||
#define __TILE_IO_RESULT_H__
|
||||
|
||||
#include <ghoul/opengl/texture.h>
|
||||
#include <modules/globebrowsing/geometry/geodetic2.h>
|
||||
|
||||
#include <ghoul/filesystem/file.h>
|
||||
|
||||
#include <modules/globebrowsing/geometry/geodetic2.h>
|
||||
#include <modules/globebrowsing/tile/tiledepthtransform.h>
|
||||
|
||||
#include "gdal_priv.h"
|
||||
@@ -39,39 +38,7 @@
|
||||
|
||||
namespace openspace {
|
||||
namespace globebrowsing {
|
||||
using namespace ghoul::opengl;
|
||||
using namespace ghoul::filesystem;
|
||||
|
||||
struct TilePreprocessData {
|
||||
std::vector<float> maxValues;
|
||||
std::vector<float> minValues;
|
||||
std::vector<bool> hasMissingData;
|
||||
|
||||
void serialize(std::ostream& s);
|
||||
static TilePreprocessData deserialize(std::istream& s);
|
||||
};
|
||||
|
||||
struct TextureFormat {
|
||||
Texture::Format ghoulFormat;
|
||||
GLuint glFormat;
|
||||
};
|
||||
|
||||
struct TileIOResult {
|
||||
TileIOResult();
|
||||
|
||||
char* imageData;
|
||||
glm::uvec3 dimensions;
|
||||
std::shared_ptr<TilePreprocessData> preprocessData;
|
||||
TileIndex tileIndex;
|
||||
CPLErr error;
|
||||
size_t nBytesImageData;
|
||||
|
||||
void serializeMetaData(std::ostream& s);
|
||||
static TileIOResult deserializeMetaData(std::istream& s);
|
||||
|
||||
static TileIOResult createDefaultRes();
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace globebrowsing
|
||||
} // namespace openspace
|
||||
|
||||
@@ -162,10 +162,10 @@ namespace globebrowsing {
|
||||
}
|
||||
|
||||
void CachingTileProvider::initTexturesFromLoadedData() {
|
||||
auto readyTileIOResults = _asyncTextureDataProvider->getTileIOResults();
|
||||
for(auto tileIOResult : readyTileIOResults){
|
||||
TileHashKey key = tileIOResult->tileIndex.hashKey();
|
||||
Tile tile = createTile(tileIOResult);
|
||||
auto rawTiles = _asyncTextureDataProvider->getRawTiles();
|
||||
for(auto rawTile : rawTiles){
|
||||
TileHashKey key = rawTile->tileIndex.hashKey();
|
||||
Tile tile = createTile(rawTile);
|
||||
_tileCache->put(key, tile);
|
||||
}
|
||||
}
|
||||
@@ -194,19 +194,19 @@ namespace globebrowsing {
|
||||
return _asyncTextureDataProvider->getTextureDataProvider()->getDepthTransform();
|
||||
}
|
||||
|
||||
Tile CachingTileProvider::createTile(std::shared_ptr<TileIOResult> tileIOResult) {
|
||||
if (tileIOResult->error != CE_None) {
|
||||
Tile CachingTileProvider::createTile(std::shared_ptr<RawTile> rawTile) {
|
||||
if (rawTile->error != CE_None) {
|
||||
return{ nullptr, nullptr, Tile::Status::IOError };
|
||||
}
|
||||
|
||||
TileHashKey key = tileIOResult->tileIndex.hashKey();
|
||||
TileHashKey key = rawTile->tileIndex.hashKey();
|
||||
TileDataLayout dataLayout =
|
||||
_asyncTextureDataProvider->getTextureDataProvider()->getDataLayout();
|
||||
|
||||
// The texture should take ownership of the data
|
||||
std::shared_ptr<Texture> texture = std::make_shared<Texture>(
|
||||
tileIOResult->imageData,
|
||||
tileIOResult->dimensions,
|
||||
rawTile->imageData,
|
||||
rawTile->dimensions,
|
||||
dataLayout.textureFormat.ghoulFormat,
|
||||
dataLayout.textureFormat.glFormat,
|
||||
dataLayout.glType,
|
||||
@@ -220,7 +220,7 @@ namespace globebrowsing {
|
||||
|
||||
Tile tile = {
|
||||
texture,
|
||||
tileIOResult->preprocessData,
|
||||
rawTile->tileMetaData,
|
||||
Tile::Status::OK
|
||||
};
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace globebrowsing {
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Collects all asynchronously downloaded <code>TileIOResult</code>
|
||||
* Collects all asynchronously downloaded <code>RawTile</code>
|
||||
* and uses <code>createTile</code> to create <code>Tile</code>s,
|
||||
* which are put in the LRU cache - potentially pushing out outdated
|
||||
* Tiles.
|
||||
@@ -90,7 +90,7 @@ namespace globebrowsing {
|
||||
* \returns A tile with <code>Tile::Status::OK</code> if no errors
|
||||
* occured, a tile with <code>Tile::Status::IOError</code> otherwise
|
||||
*/
|
||||
Tile createTile(std::shared_ptr<TileIOResult> res);
|
||||
Tile createTile(std::shared_ptr<RawTile> res);
|
||||
|
||||
/**
|
||||
* Deletes all enqueued, but not yet started async downloads of textures.
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace globebrowsing {
|
||||
_tile = Tile();
|
||||
_tile.texture = std::shared_ptr<Texture>(ghoul::io::TextureReader::ref().loadTexture(_imagePath).release());
|
||||
_tile.status = _tile.texture != nullptr ? Tile::Status::OK : Tile::Status::IOError;
|
||||
_tile.preprocessData = nullptr;
|
||||
_tile.metaData = nullptr;
|
||||
|
||||
_tile.texture->uploadTexture();
|
||||
_tile.texture->setFilter(ghoul::opengl::Texture::FilterMode::Linear);
|
||||
|
||||
@@ -102,9 +102,9 @@ namespace globebrowsing {
|
||||
for (const auto& layer : layerGroup.activeLayers()) {
|
||||
ChunkTile chunkTile = getHighestResolutionTile(layer->tileProvider(), tileIndex);
|
||||
bool tileIsOk = chunkTile.tile.status == Tile::Status::OK;
|
||||
bool tileHasPreprocessData = chunkTile.tile.preprocessData != nullptr;
|
||||
bool tileHasMetaData = chunkTile.tile.metaData != nullptr;
|
||||
bool tileIsHigherResolution = chunkTile.uvTransform.uvScale.x > mostHighResolution.uvTransform.uvScale.x;
|
||||
if (tileIsOk && tileHasPreprocessData && tileIsHigherResolution) {
|
||||
if (tileIsOk && tileHasMetaData && tileIsHigherResolution) {
|
||||
mostHighResolution = chunkTile;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user