TileIOResult -> RawTile, PreprocessData -> TileMetaData

This commit is contained in:
Erik Broberg
2016-11-07 17:01:49 +01:00
parent 05687abb65
commit ae6d27e474
19 changed files with 250 additions and 244 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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!
}

View File

@@ -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());
}

View File

@@ -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__

View File

@@ -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;

View File

@@ -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__

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -40,7 +40,7 @@
#include <algorithm>
namespace {
const std::string _loggerCat = "TileIOResult";
const std::string _loggerCat = "RawTile";
}
namespace openspace {

View File

@@ -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"

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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
};

View File

@@ -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.

View File

@@ -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);

View File

@@ -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;
}
}