Feature/tileinterpolation (#1769)

* Interpolation of tiles added to tileprovider, with additional new shaders to make this work.
 * Asset file for testing interpolation

Co-authored-by: tobiasp93 <tobias.pettersson@liu.se>
Co-authored-by: Alexander Bock <alexander.bock@liu.se>
This commit is contained in:
eriksunden
2021-11-01 09:24:40 +01:00
committed by GitHub
parent 31b908952c
commit 24ce66aad4
5 changed files with 538 additions and 37 deletions
@@ -0,0 +1,52 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* 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 "fragment.glsl"
uniform sampler2D prevTexture;
uniform sampler2D nextTexture;
uniform sampler2D colormapTexture;
uniform float blendFactor;
in vec2 texCoord;
Fragment getFragment() {
vec4 texel0 = texture2D(prevTexture, texCoord);
vec4 texel1 = texture2D(nextTexture, texCoord);
vec4 mixedTexture = mix(texel0, texel1, blendFactor);
Fragment frag;
if (mixedTexture.r > 0.999) {
vec2 position = vec2(mixedTexture.r - 0.01, 0.5);
frag.color = texture2D(colormapTexture, position);
}
else {
vec2 position = vec2(mixedTexture.r , 0.5);
frag.color = texture2D(colormapTexture, position);
}
frag.color.a = mixedTexture.a;
return frag;
}
@@ -0,0 +1,35 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* 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. *
****************************************************************************************/
#version __CONTEXT__
layout (location = 0) in vec2 in_position;
layout (location = 1) in vec2 in_texCoords;
out vec2 texCoord;
void main() {
texCoord = in_texCoords;
gl_Position = vec4(in_position, 0.0, 1.0);
}
+383 -34
View File
@@ -34,8 +34,9 @@
#include <openspace/engine/moduleengine.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/util/factorymanager.h>
#include <openspace/util/timemanager.h>
#include <openspace/util/memorymanager.h>
#include <openspace/util/spicemanager.h>
#include <openspace/util/timemanager.h>
#include <ghoul/filesystem/file.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/font/fontmanager.h>
@@ -44,6 +45,7 @@
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/profiling.h>
#include <ghoul/opengl/openglstatecache.h>
#include <ghoul/opengl/textureunit.h>
#include <filesystem>
#include <fstream>
#include "cpl_minixml.h"
@@ -142,7 +144,8 @@ namespace temporal {
constexpr const char* TimeEnd = "OpenSpaceTimeEnd";
constexpr const char* TimeResolution = "OpenSpaceTimeResolution";
constexpr const char* TimeFormat = "OpenSpaceTimeIdFormat";
constexpr const char* TimeInterpolation = "OpenSpaceTimeInterpolation";
constexpr const char* TransferFunction = "OpenSpaceTransferFunction";
constexpr openspace::properties::Property::PropertyInfo FilePathInfo = {
"FilePath",
"File Path",
@@ -291,10 +294,13 @@ TileProvider* levelProvider(TileProviderByLevel& t, int level) {
//
// Buffer needs at least 22 characters space
int timeStringify(TemporalTileProvider::TimeFormatType type, const Time& t, char* buffer)
{
std::string_view timeStringify(TemporalTileProvider::TimeFormatType type, const Time& t) {
ZoneScoped
char* buffer = reinterpret_cast<char*>(
global::memoryManager->TemporaryMemory.allocate(22)
);
std::memset(buffer, 0, 22);
const double time = t.j2000Seconds();
@@ -304,32 +310,32 @@ int timeStringify(TemporalTileProvider::TimeFormatType type, const Time& t, char
constexpr const char Format[] = "YYYY-MM-DD";
constexpr const int Size = sizeof(Format);
SpiceManager::ref().dateFromEphemerisTime(time, buffer, Size, Format);
return Size - 1;
return std::string_view(buffer, Size - 1);
}
case TemporalTileProvider::TimeFormatType::YYYYMMDD_hhmmss: {
constexpr const char Format[] = "YYYYMMDD_HRMNSC";
constexpr const int Size = sizeof(Format);
SpiceManager::ref().dateFromEphemerisTime(time, buffer, Size, Format);
return Size - 1;
return std::string_view(buffer, Size - 1);
}
case TemporalTileProvider::TimeFormatType::YYYYMMDD_hhmm: {
constexpr const char Format[] = "YYYYMMDD_HRMN";
constexpr const int Size = sizeof(Format);
SpiceManager::ref().dateFromEphemerisTime(time, buffer, Size, Format);
return Size - 1;
return std::string_view(buffer, Size - 1);
}
case TemporalTileProvider::TimeFormatType::YYYY_MM_DDThhColonmmColonssZ:
{
constexpr const char Format[] = "YYYY-MM-DDTHR:MN:SCZ";
constexpr const int Size = sizeof(Format);
SpiceManager::ref().dateFromEphemerisTime(time, buffer, Size, Format);
return Size - 1;
return std::string_view(buffer, Size - 1);
}
case TemporalTileProvider::TimeFormatType::YYYY_MM_DDThh_mm_ssZ: {
constexpr const char Format[] = "YYYY-MM-DDTHR_MN_SCZ";
constexpr const int Size = sizeof(Format);
SpiceManager::ref().dateFromEphemerisTime(time, buffer, Size, Format);
return Size - 1;
return std::string_view(buffer, Size - 1);
}
default:
throw ghoul::MissingCaseException();
@@ -387,30 +393,137 @@ TileProvider* getTileProvider(TemporalTileProvider& t, std::string_view timekey)
TileProvider* getTileProvider(TemporalTileProvider& t, const Time& time) {
ZoneScoped
if (t.useFixedTime && !t.fixedTime.value().empty()) {
try {
return getTileProvider(t, t.fixedTime.value());
}
catch (const ghoul::RuntimeError& e) {
LERRORC("TemporalTileProvider", e.message);
return nullptr;
}
}
else {
Time tCopy(time);
if (t.timeQuantizer.quantize(tCopy, true)) {
char Buffer[22];
const int size = timeStringify(t.timeFormat, tCopy, Buffer);
if (!t.interpolation) {
if (t.useFixedTime && !t.fixedTime.value().empty()) {
try {
return getTileProvider(t, std::string_view(Buffer, size));
return getTileProvider(t, t.fixedTime.value());
}
catch (const ghoul::RuntimeError& e) {
LERRORC("TemporalTileProvider", e.message);
return nullptr;
}
}
else {
Time tCopy(time);
if (t.timeQuantizer.quantize(tCopy, true)) {
std::string_view timeStr = timeStringify(t.timeFormat, tCopy);
try {
return getTileProvider(t, timeStr);
}
catch (const ghoul::RuntimeError& e) {
LERRORC("TemporalTileProvider", e.message);
return nullptr;
}
}
}
}
Time tCopy(time);
if (!t.timeQuantizer.quantize(tCopy, true)) {
return nullptr;
}
Time simulationTime(time);
Time nextTile;
Time nextNextTile;
Time prevTile;
Time secondToLast;
Time secondToFirst;
std::string_view tCopyStr = timeStringify(t.timeFormat, tCopy);
try {
t.interpolateTileProvider->t1 = getTileProvider(t, tCopyStr);
}
catch (const ghoul::RuntimeError& e) {
LERRORC("TemporalTileProvider", e.message);
return nullptr;
}
// if the images are for each hour
if (t.myResolution == "1h") {
// the second tile to interpolate between
nextTile.setTime(tCopy.j2000Seconds() + 60 * 60);
// the tile after the second tile
nextNextTile.setTime(tCopy.j2000Seconds() + 120 * 60);
// the tile before the first tile
prevTile.setTime(tCopy.j2000Seconds() - 60 * 60 + 1);
// to make sure that an image outside the dataset is not searched for both ends of
// the dataset are calculated
secondToLast.setTime(t.endTimeJ2000 - 60 * 60);
secondToFirst.setTime(t.startTimeJ2000 + 60 * 60);
}
// if the images are for each month
if (t.myResolution == "1M") {
// the second tile to interpolate between
nextTile.setTime(tCopy.j2000Seconds() + 32 * 60 * 60 * 24);
// the tile after the second tile
nextNextTile.setTime(tCopy.j2000Seconds() + 64 * 60 * 60 * 24);
// the tile before the first tile
prevTile.setTime(tCopy.j2000Seconds() - 2 * 60 * 60 * 24);
// to make sure that an image outside the dataset is not searched for both ends of
// the dataset are calculated
secondToLast.setTime(t.endTimeJ2000 - 2 * 60 * 60 * 24);
secondToFirst.setTime(t.startTimeJ2000 + 32 * 60 * 60 * 24);
// since months vary in length the time strings are set to the first of each month
auto setToFirstOfMonth = [](Time& time) {
std::string timeString = std::string(time.ISO8601());
timeString[8] = '0';
timeString[9] = '1';
time.setTime(timeString);
};
setToFirstOfMonth(nextTile);
setToFirstOfMonth(nextNextTile);
setToFirstOfMonth(prevTile);
setToFirstOfMonth(secondToLast);
setToFirstOfMonth(secondToFirst);
}
std::string_view nextTileStr = timeStringify(t.timeFormat, nextTile);
std::string_view nextNextTileStr = timeStringify(t.timeFormat, nextNextTile);
std::string_view prevTileStr = timeStringify(t.timeFormat, prevTile);
try {
// the necessary tile providers are loaded if they exist within the
// dataset's timespan
if (secondToLast.j2000Seconds() > simulationTime.j2000Seconds() &&
secondToFirst.j2000Seconds() < simulationTime.j2000Seconds())
{
t.interpolateTileProvider->t2 = getTileProvider(t, nextTileStr);
t.interpolateTileProvider->future = getTileProvider(t, nextNextTileStr);
t.interpolateTileProvider->before = getTileProvider(t, prevTileStr);
}
else if (secondToLast.j2000Seconds() < simulationTime.j2000Seconds() &&
t.endTimeJ2000 > simulationTime.j2000Seconds())
{
t.interpolateTileProvider->t2 = getTileProvider(t, nextTileStr);
t.interpolateTileProvider->future = getTileProvider(t, tCopyStr);
t.interpolateTileProvider->before = getTileProvider(t, prevTileStr);
}
else if (secondToFirst.j2000Seconds() > simulationTime.j2000Seconds() &&
t.startTimeJ2000 < simulationTime.j2000Seconds())
{
t.interpolateTileProvider->t2 = getTileProvider(t, nextTileStr);
t.interpolateTileProvider->future = getTileProvider(t, nextNextTileStr);
t.interpolateTileProvider->before = getTileProvider(t, tCopyStr);
}
else {
t.interpolateTileProvider->t2 = getTileProvider(t, tCopyStr);
t.interpolateTileProvider->future = getTileProvider(t, tCopyStr);
t.interpolateTileProvider->before = getTileProvider(t, tCopyStr);
}
t.interpolateTileProvider->factor =
(simulationTime.j2000Seconds() - tCopy.j2000Seconds()) /
(nextTile.j2000Seconds() - tCopy.j2000Seconds());
if (t.interpolateTileProvider->factor > 1) {
t.interpolateTileProvider->factor = 1;
}
return t.interpolateTileProvider.get();
}
catch (const ghoul::RuntimeError& e) {
LERRORC("TemporalTileProvider", e.message);
return nullptr;
}
return nullptr;
}
void ensureUpdated(TemporalTileProvider& t) {
@@ -422,10 +535,10 @@ void ensureUpdated(TemporalTileProvider& t) {
}
std::string xmlValue(TemporalTileProvider& t, CPLXMLNode* node, const std::string& key,
const std::string& defaultVal)
const std::string& defaultVal, bool isOptional = false)
{
CPLXMLNode* n = CPLSearchXMLNode(node, key.c_str());
if (!n) {
if (!n && !isOptional) {
throw ghoul::RuntimeError(
fmt::format("Unable to parse file {}. {} missing", t.filePath.value(), key)
);
@@ -449,10 +562,20 @@ std::string consumeTemporalMetaData(TemporalTileProvider& t, const std::string&
temporal::TimeFormat,
"YYYY-MM-DDThh:mm:ssZ"
);
std::string timeInterpolation = xmlValue(
t,
node,
temporal::TimeInterpolation,
"none",
true
);
t.colormap = xmlValue(t, node, temporal::TransferFunction, "none", true);
Time start;
start.setTime(std::move(timeStart));
Time end(Time::now());
Time start = Time(timeStart);
Time end = Time::now();
Time endOfInterval = Time(timeEnd);
t.startTimeJ2000 = start.j2000Seconds();
t.endTimeJ2000 = endOfInterval.j2000Seconds();
if (timeEnd == "Yesterday") {
end.advanceTime(-60.0 * 60.0 * 24.0); // Go back one day
}
@@ -466,6 +589,7 @@ std::string consumeTemporalMetaData(TemporalTileProvider& t, const std::string&
std::string(end.ISO8601())
);
t.timeQuantizer.setResolution(timeResolution);
t.myResolution = timeResolution;
}
catch (const ghoul::RuntimeError& e) {
throw ghoul::RuntimeError(fmt::format(
@@ -474,6 +598,7 @@ std::string consumeTemporalMetaData(TemporalTileProvider& t, const std::string&
));
}
t.timeFormat = ghoul::from_string<TemporalTileProvider::TimeFormatType>(timeIdFormat);
t.interpolation = (timeInterpolation == "linear");
CPLXMLNode* gdalNode = CPLSearchXMLNode(node, "GDAL_WMS");
if (gdalNode) {
@@ -492,10 +617,10 @@ std::string consumeTemporalMetaData(TemporalTileProvider& t, const std::string&
}
}
bool readFilePath(TemporalTileProvider& t) {
void readFilePath(TemporalTileProvider& t) {
ZoneScoped
std::ifstream in(t.filePath.value().c_str());
std::ifstream in(t.filePath.value());
std::string xml;
if (in.is_open()) {
// read file
@@ -516,7 +641,6 @@ bool readFilePath(TemporalTileProvider& t) {
}
t.gdalXmlTemplate = consumeTemporalMetaData(t, xml);
return true;
}
} // namespace
@@ -874,11 +998,21 @@ TemporalTileProvider::TemporalTileProvider(const ghoul::Dictionary& dictionary)
}
addProperty(fixedTime);
successfulInitialization = readFilePath(*this);
readFilePath(*this);
successfulInitialization = true;
if (!successfulInitialization) {
LERRORC("TemporalTileProvider", "Unable to read file " + filePath.value());
}
if (interpolation) {
interpolateTileProvider = std::make_unique<InterpolateTileProvider>(dictionary);
interpolateTileProvider->colormap = colormap;
initialize(*interpolateTileProvider);
ghoul::Dictionary dict;
dict.setValue("FilePath", colormap);
interpolateTileProvider->singleImageProvider =
std::make_unique<SingleImageProvider>(dict);
}
}
@@ -933,6 +1067,8 @@ bool initialize(TileProvider& tp) {
}
return success;
}
case Type::InterpolateTileProvider:
break;
case Type::TemporalTileProvider:
break;
default:
@@ -975,6 +1111,8 @@ bool deinitialize(TileProvider& tp) {
}
return success;
}
case Type::InterpolateTileProvider:
break;
case Type::TemporalTileProvider:
break;
default:
@@ -984,8 +1122,175 @@ bool deinitialize(TileProvider& tp) {
}
//
// InterpolateTileProvider
//
InterpolateTileProvider::InterpolateTileProvider(const ghoul::Dictionary&) {
ZoneScoped
type = Type::InterpolateTileProvider;
glGenFramebuffers(1, &fbo);
glGenVertexArrays(1, &vaoQuad);
glGenBuffers(1, &vboQuad);
glBindVertexArray(vaoQuad);
glBindBuffer(GL_ARRAY_BUFFER, vboQuad);
tileCache = global::moduleEngine->module<GlobeBrowsingModule>()->tileCache();
// Quad for fullscreen with vertex (xy) and texture coordinates (uv)
const GLfloat vertexData[] = {
// x y u v
-1.f, -1.f, 0.f, 0.f,
1.f, 1.f, 1.f, 1.f,
-1.f, 1.f, 0.f, 1.f,
-1.f, -1.f, 0.f, 0.f,
1.f, -1.f, 1.f, 0.f,
1.f, 1.f, 1.f, 1.f
};
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
// vertex coordinates at location 0
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), nullptr);
glEnableVertexAttribArray(0);
// texture coords at location 1
glVertexAttribPointer(
1,
2,
GL_FLOAT,
GL_FALSE,
4 * sizeof(GLfloat),
reinterpret_cast<void*>(sizeof(GLfloat) * 2)
);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
shaderProgram = global::renderEngine->buildRenderProgram(
"InterpolatingProgram",
absPath("${MODULE_GLOBEBROWSING}/shaders/interpolate_vs.glsl"),
absPath("${MODULE_GLOBEBROWSING}/shaders/interpolate_fs.glsl")
);
}
InterpolateTileProvider::~InterpolateTileProvider() {
glDeleteFramebuffers(1, &fbo);
glDeleteBuffers(1, &vboQuad);
glDeleteVertexArrays(1, &vaoQuad);
}
Tile InterpolateTileProvider::calculateTile(const TileIndex& tileIndex) {
ZoneScoped
TracyGpuZone("tile");
// prev and next are the two tiles to interpolate between
Tile prev = tile(*t1, tileIndex);
Tile next = tile(*t2, tileIndex);
// the tile before and the tile after the interpolation interval are loaded so the
// interpolation goes smoother
Tile prevprev = tile(*before, tileIndex);
Tile nextnext = tile(*future, tileIndex);
cache::ProviderTileKey key = { tileIndex, uniqueIdentifier };
if (!prev.texture || !next.texture) {
return Tile{ nullptr, std::nullopt, Tile::Status::Unavailable };
}
// There is a previous and next texture to interpolate between so do the interpolation
// The texture that will give the color for the interpolated texture
ghoul::opengl::Texture* colormapTexture = singleImageProvider->tile.texture;
long long hkey = cache::ProviderTileHasher()(key);
// The data for initializing the texture
TileTextureInitData initData(
prev.texture->dimensions().x,
prev.texture->dimensions().y,
prev.texture->dataType(),
prev.texture->format(),
TileTextureInitData::PadTiles::No,
TileTextureInitData::ShouldAllocateDataOnCPU::No
);
// Check if a tile exists for the given key in the tileCache
// Initializing the tile that will contian the interpolated texture
Tile ourTile;
// The texture that will contain the interpolated image
ghoul::opengl::Texture* writeTexture;
if (tileCache->exist(key)) {
// Get the tile from the tilecache
ourTile = tileCache->get(key);
// Use the texture from the tileCache
writeTexture = ourTile.texture;
}
else {
// Create a texture with the initialization data
writeTexture = tileCache->texture(initData);
// Create a tile with the texture
ourTile = Tile{ writeTexture, std::nullopt, Tile::Status::OK };
// Add it to the tilecache
tileCache->put(key, initData.hashKey, ourTile);
}
// Saves current state
GLint currentFBO;
GLint viewport[4];
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &currentFBO);
global::renderEngine->openglStateCache().viewport(viewport);
// Bind render texture to FBO
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture(
GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
*writeTexture,
0
);
glDisable(GL_BLEND);
GLenum textureBuffers[1] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, textureBuffers);
// Check that our framebuffer is ok
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
LERRORC("TileProvider", "Incomplete framebuffer");
}
// Setup our own viewport settings
GLsizei w = static_cast<GLsizei>(writeTexture->width());
GLsizei h = static_cast<GLsizei>(writeTexture->height());
glViewport(0, 0, w, h);
glClearColor(0.f, 0.f, 0.f, 0.f);
glClear(GL_COLOR_BUFFER_BIT);
GLint id;
glGetIntegerv(GL_CURRENT_PROGRAM, &id);
// Activate shader and bind uniforms
shaderProgram->activate();
shaderProgram->setUniform("blendFactor", factor);
ghoul::opengl::TextureUnit colormapUnit;
colormapUnit.activate();
colormapTexture->bind();
shaderProgram->setUniform("colormapTexture", colormapUnit);
ghoul::opengl::TextureUnit prevUnit;
prevUnit.activate();
prev.texture->bind();
shaderProgram->setUniform("prevTexture", prevUnit);
ghoul::opengl::TextureUnit nextUnit;
nextUnit.activate();
next.texture->bind();
shaderProgram->setUniform("nextTexture", nextUnit);
// Render to the texture
glBindVertexArray(vaoQuad);
glDrawArrays(GL_TRIANGLES, 0, 6); // 2 triangles
// Deactivate shader program (when rendering is completed)
shaderProgram->deactivate();
glUseProgram(id);
// Restores system state
glBindFramebuffer(GL_FRAMEBUFFER, currentFBO);
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
// Restores OpenGL Rendering State
global::renderEngine->openglStateCache().resetColorState();
global::renderEngine->openglStateCache().resetBlendState();
global::renderEngine->openglStateCache().resetDepthState();
global::renderEngine->openglStateCache().resetPolygonAndClippingState();
global::renderEngine->openglStateCache().resetViewportState();
return ourTile;
}
Tile tile(TileProvider& tp, const TileIndex& tileIndex) {
@@ -1091,6 +1396,13 @@ Tile tile(TileProvider& tp, const TileIndex& tileIndex) {
return Tile();
}
}
case Type::InterpolateTileProvider: {
ZoneScopedN("Type::InterpolateTileProvider")
InterpolateTileProvider& t = static_cast<InterpolateTileProvider&>(tp);
return t.calculateTile(tileIndex);
break;
}
case Type::TemporalTileProvider: {
ZoneScopedN("Type::TemporalTileProvider")
TemporalTileProvider& t = static_cast<TemporalTileProvider&>(tp);
@@ -1152,6 +1464,17 @@ Tile::Status tileStatus(TileProvider& tp, const TileIndex& index) {
TileProvider* provider = levelProvider(t, index.level);
return provider ? tileStatus(*provider, index) : Tile::Status::Unavailable;
}
case Type::InterpolateTileProvider: {
InterpolateTileProvider& t = static_cast<InterpolateTileProvider&>(tp);
Tile::Status t1Stat = tileStatus(*t.t1, index);
Tile::Status t2Stat = tileStatus(*t.t2, index);
if (t1Stat <= t2Stat) {
return t1Stat;
}
else {
return t2Stat;
}
}
case Type::TemporalTileProvider: {
TemporalTileProvider& t = static_cast<TemporalTileProvider&>(tp);
if (t.successfulInitialization) {
@@ -1197,6 +1520,10 @@ TileDepthTransform depthTransform(TileProvider& tp) {
}
case Type::ByLevelTileProvider:
return { 0.f, 1.f };
case Type::InterpolateTileProvider: {
InterpolateTileProvider& t = static_cast<InterpolateTileProvider&>(tp);
return depthTransform(*t.t1);
}
case Type::TemporalTileProvider: {
TemporalTileProvider& t = static_cast<TemporalTileProvider&>(tp);
if (t.successfulInitialization) {
@@ -1265,6 +1592,14 @@ int update(TileProvider& tp) {
}
break;
}
case Type::InterpolateTileProvider: {
InterpolateTileProvider& t = static_cast<InterpolateTileProvider&>(tp);
update(*t.t1);
update(*t.t2);
update(*t.before);
update(*t.future);
break;
}
case Type::TemporalTileProvider: {
TemporalTileProvider& t = static_cast<TemporalTileProvider&>(tp);
if (t.successfulInitialization) {
@@ -1356,6 +1691,14 @@ void reset(TileProvider& tp) {
}
break;
}
case Type::InterpolateTileProvider: {
InterpolateTileProvider& t = static_cast<InterpolateTileProvider&>(tp);
reset(*t.t1);
reset(*t.t2);
reset(*t.before);
reset(*t.future);
break;
}
case Type::TemporalTileProvider: {
TemporalTileProvider& t = static_cast<TemporalTileProvider&>(tp);
if (t.successfulInitialization) {
@@ -1402,6 +1745,10 @@ int maxLevel(TileProvider& tp) {
TileProviderByLevel& t = static_cast<TileProviderByLevel&>(tp);
return static_cast<int>(t.providerIndices.size() - 1);
}
case Type::InterpolateTileProvider: {
InterpolateTileProvider& t = static_cast<InterpolateTileProvider&>(tp);
return glm::min(maxLevel(*t.t1), maxLevel(*t.t2));
}
case Type::TemporalTileProvider: {
TemporalTileProvider& t = static_cast<TemporalTileProvider&>(tp);
if (t.successfulInitialization) {
@@ -1443,6 +1790,8 @@ float noDataValueAsFloat(TileProvider& tp) {
return std::numeric_limits<float>::min();
case Type::ByLevelTileProvider:
return std::numeric_limits<float>::min();
case Type::InterpolateTileProvider:
return std::numeric_limits<float>::min();
case Type::TemporalTileProvider:
return std::numeric_limits<float>::min();
default:
+29 -3
View File
@@ -37,7 +37,7 @@
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/intproperty.h>
#include <unordered_map>
#include <ghoul/opengl/programobject.h>
struct CPLXMLNode;
namespace ghoul::fontrendering {
@@ -63,7 +63,8 @@ enum class Type {
TemporalTileProvider,
TileIndexTileProvider,
ByIndexTileProvider,
ByLevelTileProvider
ByLevelTileProvider,
InterpolateTileProvider
};
@@ -104,6 +105,25 @@ struct SingleImageProvider : public TileProvider {
properties::StringProperty filePath;
};
struct InterpolateTileProvider : public TileProvider {
InterpolateTileProvider(const ghoul::Dictionary&);
virtual ~InterpolateTileProvider();
Tile calculateTile(const TileIndex&);
TileProvider* before = nullptr;
TileProvider* t1 = nullptr;
TileProvider* t2 = nullptr;
TileProvider* future = nullptr;
float factor = 1.f;
GLuint vaoQuad = 0;
GLuint vboQuad = 0;
GLuint fbo = 0;
std::string colormap;
std::unique_ptr<ghoul::opengl::ProgramObject> shaderProgram;
std::unique_ptr<SingleImageProvider> singleImageProvider;
cache::MemoryAwareTileCache* tileCache = nullptr;
};
struct TextTileProvider : public TileProvider {
TextTileProvider(TileTextureInitData initData, size_t fontSize = 48);
@@ -181,12 +201,18 @@ struct TemporalTileProvider : public TileProvider {
std::unordered_map<TimeKey, std::unique_ptr<TileProvider>> tileProviderMap;
TileProvider* currentTileProvider = nullptr;
bool interpolation = false;
TileProvider* currentTileProvider = nullptr;
double startTimeJ2000;
double endTimeJ2000;
TimeFormatType timeFormat;
TimeQuantizer timeQuantizer;
std::string colormap;
std::string myResolution;
bool successfulInitialization = false;
std::unique_ptr<InterpolateTileProvider> interpolateTileProvider;
};