Feature/globebrowsing speedup (#735)

* Removal of ChunkRenderer, ChunkedLodGlobe, ChunkCuller, chunklevel evaluator, culling classes, layershadermanager, GpuLayer, GPUData, ChunkNode, Grid, BasicGrid, Chunk files, Angle, AABB classes, PointGlobe, Ellipsoid, TileSelector, tiledatatype, iodescription, simplerawtilerreader, rawtilereader
 * Less dynamic allocation for SkirtedGrid, LayerManager, RenderableGlobe, TextureUnit
 * Clean up memory management in RawTiles
 * Code simplification
 * Optimize shader uniform setting
 * Introduce UniformCache
 * Callback simplification
 * Turn ChunkNode into a struct
 * Use a MemoryPool to organize all ChunkNodes rather than use unique_ptr and the necessary memory allocation
 * Collect draw calls
 * Consolidate fragment shaders between local and global renderer
 * Shader cleanup and optimization
 * Update CMake to not include included shaders
 * Integrate traversal function into the looping
 * Replace std::queue with std::vector
 * Merge TextureContainer into MemoryAwareTileCache
 * Lazy computation of chunk bounding boxes
 * Memory management of LayerGroup
 * Remove class hierarchy from tileproviders (temporaltileprovider not working yet)
 * Remove PBO classes
* Chunk status stored in Chunk
* Don't create a copy of the ChunkTilePile
* Enable culling by projected area on default
* Have raw tile reader return a Tile instead of a shared_ptr to a tile
* Start making GDAL mandatory
* Increase the default lod scale factor to 15
This commit is contained in:
Alexander Bock
2018-10-30 17:20:06 -04:00
committed by GitHub
parent cf8d2db914
commit 9047dc7a3e
198 changed files with 6929 additions and 15994 deletions

View File

@@ -137,7 +137,7 @@ public:
void setRenderable(std::unique_ptr<Renderable> renderable);
const Renderable* renderable() const;
//Renderable* renderable();
Renderable* renderable();
const std::string& guiPath() const;
bool hasGuiHintHidden() const;

View File

@@ -1,107 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_CORE___GPUDATA___H__
#define __OPENSPACE_CORE___GPUDATA___H__
#include <ghoul/opengl/programobject.h>
#include <ghoul/opengl/texture.h>
#include <ghoul/opengl/textureunit.h>
#include <string>
#include <memory>
// @TODO: This class should disappear as it doesn't server much of a purpose and only
// complicates local reasoning
namespace openspace {
/**
* Manages a GPU representation of the templated data type T.
* This class provides a simple interface setting the value of
* the binded GLSL variable.
*/
template<typename T>
class GPUData {
public:
/**
* Updates the uniform location of the uniform variable named <name>
* in the provided shader program.
*/
void bind(ghoul::opengl::ProgramObject* program, const std::string& name) {
_uniformLocation = program->uniformLocation(name);
}
/**
* Sets the value of T to its corresponding GPU value.
* OBS! Users must ensure bind has been called before using this method
*/
void setValue(ghoul::opengl::ProgramObject* program, T val) {
program->setUniform(_uniformLocation, val);
}
protected:
GLint _uniformLocation = -1;
};
/**
* Manages a Texture on the GPU.
* This class provides a simple interface binding texture to the
* named uniform.
*/
class GPUTexture {
public:
/**
* Updates the uniform location of the uniform variable named <name>
* in the provided shader program.
*/
void bind(ghoul::opengl::ProgramObject* program, const std::string& name) {
_uniformLocation = program->uniformLocation(name);
}
/**
* Sets and assignes a texture unit within the provided shader
* program.
* OBS! Users must ensure bind has been called before using this method.
*/
void setValue(ghoul::opengl::ProgramObject* program, ghoul::opengl::Texture* texture){
_texUnit = std::make_unique<ghoul::opengl::TextureUnit>();
_texUnit->activate();
if (texture) {
texture->bind();
}
program->setUniform(_uniformLocation, *_texUnit);
}
void deactivate() {
_texUnit = nullptr;
}
private:
std::unique_ptr<ghoul::opengl::TextureUnit> _texUnit;
GLint _uniformLocation = -1;
};
} // namespace openspace
#endif // __OPENSPACE_CORE___GPUDATA___H__

View File

@@ -37,7 +37,7 @@ struct Job {
virtual ~Job() = default;
virtual void execute() = 0;
virtual std::shared_ptr<P> product() = 0;
virtual P product() = 0;
};
} // namespace openspace

View File

@@ -55,9 +55,9 @@
namespace {
static const char* _loggerCat = "RenderableAtmosphere";
const char* keyShadowGroup = "ShadowGroup";
const char* keyShadowSource = "Source";
const char* keyShadowCaster = "Caster";
const char* KeyShadowGroup = "ShadowGroup";
const char* KeyShadowSource = "Source";
const char* KeyShadowCaster = "Caster";
const char* keyAtmosphere = "Atmosphere";
const char* keyAtmosphereRadius = "AtmosphereRadius";
@@ -293,18 +293,18 @@ RenderableAtmosphere::RenderableAtmosphere(const ghoul::Dictionary& dictionary)
//======== Reads Shadow (Eclipses) Entries in mod file ===========
//================================================================
ghoul::Dictionary shadowDictionary;
bool success = dictionary.getValue(keyShadowGroup, shadowDictionary);
bool success = dictionary.getValue(KeyShadowGroup, shadowDictionary);
bool disableShadows = false;
if (success) {
std::vector<std::pair<std::string, double>> sourceArray;
unsigned int sourceCounter = 1;
while (success) {
std::string sourceName;
success = shadowDictionary.getValue(keyShadowSource +
success = shadowDictionary.getValue(KeyShadowSource +
std::to_string(sourceCounter) + ".Name", sourceName);
if (success) {
double sourceRadius;
success = shadowDictionary.getValue(keyShadowSource +
success = shadowDictionary.getValue(KeyShadowSource +
std::to_string(sourceCounter) + ".Radius", sourceRadius);
if (success) {
sourceArray.emplace_back(sourceName, sourceRadius);
@@ -329,11 +329,11 @@ RenderableAtmosphere::RenderableAtmosphere(const ghoul::Dictionary& dictionary)
unsigned int casterCounter = 1;
while (success) {
std::string casterName;
success = shadowDictionary.getValue(keyShadowCaster +
success = shadowDictionary.getValue(KeyShadowCaster +
std::to_string(casterCounter) + ".Name", casterName);
if (success) {
double casterRadius;
success = shadowDictionary.getValue(keyShadowCaster +
success = shadowDictionary.getValue(KeyShadowCaster +
std::to_string(casterCounter) + ".Radius", casterRadius);
if (success) {
casterArray.emplace_back(casterName, casterRadius);

View File

@@ -227,21 +227,6 @@ void DebugRenderer::renderCameraFrustum(const RenderData& data, const Camera& ot
glEnable(GL_CULL_FACE);
}
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED
void DebugRenderer::renderAABB2(const globebrowsing::AABB2& screenSpaceAABB,
const glm::vec4& rgba) const
{
Vertices vertices = {
glm::vec4(screenSpaceAABB.min.x, screenSpaceAABB.min.y, 1, 1),
glm::vec4(screenSpaceAABB.min.x, screenSpaceAABB.max.y, 1, 1),
glm::vec4(screenSpaceAABB.max.x, screenSpaceAABB.min.y, 1, 1),
glm::vec4(screenSpaceAABB.max.x, screenSpaceAABB.max.y, 1, 1)
};
renderVertices(vertices, GL_LINES, rgba);
}
#endif // OPENSPACE_MODULE_GLOBEBROWSING_ENABLED
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED
const DebugRenderer::Vertices DebugRenderer::verticesFor(
const globebrowsing::AABB3& screenSpaceAABB) const

View File

@@ -28,7 +28,7 @@
#include <openspace/util/updatestructures.h>
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED
#include <modules/globebrowsing/geometry/aabb.h>
#include <modules/globebrowsing/src/basictypes.h>
#endif // OPENSPACE_MODULE_GLOBEBROWSING_ENABLED
#include <ghoul/glm.h>
@@ -132,15 +132,6 @@ public:
void renderCameraFrustum(const RenderData& data, const Camera& otherCamera,
const glm::vec4& rgba = { 1.f, 1.f, 1.f, 0.3f }) const;
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED
/**
* Renders a screen space AABB2 to the screen with the provided color
*/
void renderAABB2(const globebrowsing::AABB2& screenSpaceAABB,
const glm::vec4& rgba = { 1.f, 1.f, 1.f, 0.3f }) const;
#endif // OPENSPACE_MODULE_GLOBEBROWSING_ENABLED
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED
/**
* Takes a AABB3 in screen space and returns vertices representing the corner points

View File

@@ -26,201 +26,76 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake)
set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/globebrowsingmodule.h
${CMAKE_CURRENT_SOURCE_DIR}/cache/lrucache.h
${CMAKE_CURRENT_SOURCE_DIR}/cache/lrucache.inl
${CMAKE_CURRENT_SOURCE_DIR}/cache/memoryawaretilecache.h
${CMAKE_CURRENT_SOURCE_DIR}/cache/texturecontainer.h
${CMAKE_CURRENT_SOURCE_DIR}/chunk/chunk.h
${CMAKE_CURRENT_SOURCE_DIR}/chunk/chunknode.h
${CMAKE_CURRENT_SOURCE_DIR}/chunk/chunklevelevaluator/chunklevelevaluator.h
${CMAKE_CURRENT_SOURCE_DIR}/chunk/chunklevelevaluator/availabletiledataevaluator.h
${CMAKE_CURRENT_SOURCE_DIR}/chunk/chunklevelevaluator/distanceevaluator.h
${CMAKE_CURRENT_SOURCE_DIR}/chunk/chunklevelevaluator/projectedareaevaluator.h
${CMAKE_CURRENT_SOURCE_DIR}/chunk/culling/chunkculler.h
${CMAKE_CURRENT_SOURCE_DIR}/chunk/culling/frustumculler.h
${CMAKE_CURRENT_SOURCE_DIR}/chunk/culling/horizonculler.h
${CMAKE_CURRENT_SOURCE_DIR}/dashboard/dashboarditemglobelocation.h
${CMAKE_CURRENT_SOURCE_DIR}/geometry/aabb.h
${CMAKE_CURRENT_SOURCE_DIR}/geometry/angle.h
${CMAKE_CURRENT_SOURCE_DIR}/geometry/angle.inl
${CMAKE_CURRENT_SOURCE_DIR}/geometry/ellipsoid.h
${CMAKE_CURRENT_SOURCE_DIR}/geometry/geodetic2.h
${CMAKE_CURRENT_SOURCE_DIR}/geometry/geodetic3.h
${CMAKE_CURRENT_SOURCE_DIR}/geometry/geodeticpatch.h
${CMAKE_CURRENT_SOURCE_DIR}/globes/chunkedlodglobe.h
${CMAKE_CURRENT_SOURCE_DIR}/globes/pointglobe.h
${CMAKE_CURRENT_SOURCE_DIR}/globes/renderableglobe.h
${CMAKE_CURRENT_SOURCE_DIR}/meshes/basicgrid.h
${CMAKE_CURRENT_SOURCE_DIR}/meshes/grid.h
${CMAKE_CURRENT_SOURCE_DIR}/meshes/skirtedgrid.h
${CMAKE_CURRENT_SOURCE_DIR}/meshes/trianglesoup.h
${CMAKE_CURRENT_SOURCE_DIR}/other/prioritizingconcurrentjobmanager.h
${CMAKE_CURRENT_SOURCE_DIR}/other/prioritizingconcurrentjobmanager.inl
${CMAKE_CURRENT_SOURCE_DIR}/other/pixelbuffer.h
${CMAKE_CURRENT_SOURCE_DIR}/other/pixelbuffercontainer.h
${CMAKE_CURRENT_SOURCE_DIR}/other/pixelbuffercontainer.inl
${CMAKE_CURRENT_SOURCE_DIR}/other/statscollector.h
${CMAKE_CURRENT_SOURCE_DIR}/other/templatedstatscollector.h
${CMAKE_CURRENT_SOURCE_DIR}/other/templatedstatscollector.inl
${CMAKE_CURRENT_SOURCE_DIR}/other/timequantizer.h
${CMAKE_CURRENT_SOURCE_DIR}/other/lruthreadpool.h
${CMAKE_CURRENT_SOURCE_DIR}/other/lruthreadpool.inl
${CMAKE_CURRENT_SOURCE_DIR}/rendering/chunkrenderer.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layershadermanager.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpuchunktile.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpuchunktilepile.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpuheightlayer.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayer.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayeradjustment.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayergroup.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayermanager.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayerrendersettings.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gputiledepthtransform.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gputileuvtransform.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layer.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layeradjustment.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layergroup.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layergroupid.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layermanager.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layerrendersettings.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/asynctiledataprovider.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/chunktile.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/pixelregion.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtile.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/textureformat.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tile.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tiledepthtransform.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileindex.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tilemetadata.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileselector.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileuvtransform.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileloadjob.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/defaulttileprovider.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/singleimageprovider.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/sizereferencetileprovider.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/temporaltileprovider.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/texttileprovider.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileindextileprovider.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileprovider.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileproviderbyindex.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileproviderbylevel.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tiletextureinitdata.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtiledatareader/rawtiledatareader.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtiledatareader/gdalrawtiledatareader.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtiledatareader/simplerawtiledatareader.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtiledatareader/gdalwrapper.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtiledatareader/iodescription.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtiledatareader/tiledatatype.h
${CMAKE_CURRENT_SOURCE_DIR}/src/asynctiledataprovider.h
${CMAKE_CURRENT_SOURCE_DIR}/src/basictypes.h
${CMAKE_CURRENT_SOURCE_DIR}/src/dashboarditemglobelocation.h
${CMAKE_CURRENT_SOURCE_DIR}/src/ellipsoid.h
${CMAKE_CURRENT_SOURCE_DIR}/src/gdalwrapper.h
${CMAKE_CURRENT_SOURCE_DIR}/src/geodeticpatch.h
${CMAKE_CURRENT_SOURCE_DIR}/src/gpulayergroup.h
${CMAKE_CURRENT_SOURCE_DIR}/src/layer.h
${CMAKE_CURRENT_SOURCE_DIR}/src/layeradjustment.h
${CMAKE_CURRENT_SOURCE_DIR}/src/layergroup.h
${CMAKE_CURRENT_SOURCE_DIR}/src/layergroupid.h
${CMAKE_CURRENT_SOURCE_DIR}/src/layermanager.h
${CMAKE_CURRENT_SOURCE_DIR}/src/layerrendersettings.h
${CMAKE_CURRENT_SOURCE_DIR}/src/lrucache.h
${CMAKE_CURRENT_SOURCE_DIR}/src/lrucache.inl
${CMAKE_CURRENT_SOURCE_DIR}/src/lruthreadpool.h
${CMAKE_CURRENT_SOURCE_DIR}/src/lruthreadpool.inl
${CMAKE_CURRENT_SOURCE_DIR}/src/memoryawaretilecache.h
${CMAKE_CURRENT_SOURCE_DIR}/src/prioritizingconcurrentjobmanager.h
${CMAKE_CURRENT_SOURCE_DIR}/src/prioritizingconcurrentjobmanager.inl
${CMAKE_CURRENT_SOURCE_DIR}/src/rawtile.h
${CMAKE_CURRENT_SOURCE_DIR}/src/rawtiledatareader.h
${CMAKE_CURRENT_SOURCE_DIR}/src/renderableglobe.h
${CMAKE_CURRENT_SOURCE_DIR}/src/skirtedgrid.h
${CMAKE_CURRENT_SOURCE_DIR}/src/tileindex.h
${CMAKE_CURRENT_SOURCE_DIR}/src/tileloadjob.h
${CMAKE_CURRENT_SOURCE_DIR}/src/tileprovider.h
${CMAKE_CURRENT_SOURCE_DIR}/src/tiletextureinitdata.h
${CMAKE_CURRENT_SOURCE_DIR}/src/timequantizer.h
)
set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/globebrowsingmodule.cpp
${CMAKE_CURRENT_SOURCE_DIR}/globebrowsingmodule_lua.inl
${CMAKE_CURRENT_SOURCE_DIR}/cache/memoryawaretilecache.cpp
${CMAKE_CURRENT_SOURCE_DIR}/cache/texturecontainer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/chunk/chunk.cpp
${CMAKE_CURRENT_SOURCE_DIR}/chunk/chunknode.cpp
${CMAKE_CURRENT_SOURCE_DIR}/chunk/chunklevelevaluator/availabletiledataevaluator.cpp
${CMAKE_CURRENT_SOURCE_DIR}/chunk/chunklevelevaluator/distanceevaluator.cpp
${CMAKE_CURRENT_SOURCE_DIR}/chunk/chunklevelevaluator/projectedareaevaluator.cpp
${CMAKE_CURRENT_SOURCE_DIR}/chunk/culling/frustumculler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/chunk/culling/horizonculler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/dashboard/dashboarditemglobelocation.cpp
${CMAKE_CURRENT_SOURCE_DIR}/geometry/aabb.cpp
${CMAKE_CURRENT_SOURCE_DIR}/geometry/ellipsoid.cpp
${CMAKE_CURRENT_SOURCE_DIR}/geometry/geodetic2.cpp
${CMAKE_CURRENT_SOURCE_DIR}/geometry/geodeticpatch.cpp
${CMAKE_CURRENT_SOURCE_DIR}/globes/chunkedlodglobe.cpp
${CMAKE_CURRENT_SOURCE_DIR}/globes/pointglobe.cpp
${CMAKE_CURRENT_SOURCE_DIR}/globes/renderableglobe.cpp
${CMAKE_CURRENT_SOURCE_DIR}/meshes/basicgrid.cpp
${CMAKE_CURRENT_SOURCE_DIR}/meshes/grid.cpp
${CMAKE_CURRENT_SOURCE_DIR}/meshes/skirtedgrid.cpp
${CMAKE_CURRENT_SOURCE_DIR}/meshes/trianglesoup.cpp
${CMAKE_CURRENT_SOURCE_DIR}/other/pixelbuffer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/other/statscollector.cpp
${CMAKE_CURRENT_SOURCE_DIR}/other/timequantizer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/chunkrenderer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layershadermanager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpuchunktile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpuchunktilepile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpuheightlayer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayeradjustment.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayergroup.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayermanager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayerrendersettings.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gputiledepthtransform.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gputileuvtransform.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layeradjustment.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layergroup.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layergroupid.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layermanager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layerrendersettings.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/asynctiledataprovider.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/pixelregion.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/tile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileindex.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/tilemetadata.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileselector.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileloadjob.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/defaulttileprovider.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/singleimageprovider.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/sizereferencetileprovider.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/temporaltileprovider.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/texttileprovider.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileindextileprovider.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileprovider.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileproviderbyindex.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileproviderbylevel.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/tiletextureinitdata.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtiledatareader/rawtiledatareader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtiledatareader/gdalrawtiledatareader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtiledatareader/simplerawtiledatareader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtiledatareader/gdalwrapper.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtiledatareader/iodescription.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtiledatareader/tiledatatype.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/asynctiledataprovider.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/dashboarditemglobelocation.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/ellipsoid.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/gdalwrapper.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/geodeticpatch.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/gpulayergroup.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/layer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/layeradjustment.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/layergroup.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/layergroupid.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/layermanager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/layerrendersettings.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/memoryawaretilecache.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/rawtile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/rawtiledatareader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/renderableglobe.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/skirtedgrid.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/tileindex.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/tileloadjob.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/tileprovider.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/tiletextureinitdata.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/timequantizer.cpp
)
source_group("Source Files" FILES ${SOURCE_FILES})
set(SHADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/shaders/blending.hglsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/ellipsoid.hglsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/globalchunkedlodpatch_vs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/globalchunkedlodpatch_fs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/localchunkedlodpatch_vs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/localchunkedlodpatch_fs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/pointglobe_vs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/pointglobe_fs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/globalrenderer_vs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/localrenderer_vs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/renderer_fs.glsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/texturetilemapping.hglsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/tile.hglsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/tilefragment.hglsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/tileheight.hglsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/tilevertexskirt.hglsl
${CMAKE_CURRENT_SOURCE_DIR}/shaders/globeshading.hglsl
)
source_group("Shader Files" FILES ${SHADER_FILES})
@@ -232,36 +107,31 @@ create_new_module(
${HEADER_FILES} ${SOURCE_FILES} ${SHADER_FILES}
)
option(OPENSPACE_MODULE_GLOBEBROWSING_USE_GDAL "Use GDAL" ON)
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/gdal_data DESTINATION modules/globebrowsing)
if (OPENSPACE_MODULE_GLOBEBROWSING_USE_GDAL)
if (WIN32)
target_include_directories(
openspace-module-globebrowsing
SYSTEM PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/ext/gdal/include
)
if (WIN32)
target_include_directories(
openspace-module-globebrowsing
SYSTEM PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/ext/gdal/include
)
target_link_libraries(
openspace-module-globebrowsing
${CMAKE_CURRENT_SOURCE_DIR}/ext/gdal/lib/gdal_i.lib
)
register_external_libraries("${CMAKE_CURRENT_SOURCE_DIR}/ext/gdal/lib/gdal202.dll")
else (WIN32)
find_package(GDAL REQUIRED)
target_link_libraries(
openspace-module-globebrowsing
${CMAKE_CURRENT_SOURCE_DIR}/ext/gdal/lib/gdal_i.lib
)
register_external_libraries("${CMAKE_CURRENT_SOURCE_DIR}/ext/gdal/lib/gdal202.dll")
else (WIN32)
find_package(GDAL REQUIRED)
target_include_directories(
openspace-module-globebrowsing
SYSTEM PUBLIC
${GDAL_INCLUDE_DIR}
)
target_include_directories(
openspace-module-globebrowsing
SYSTEM PUBLIC
${GDAL_INCLUDE_DIR}
)
target_link_libraries(openspace-module-globebrowsing ${GDAL_LIBRARY})
target_link_libraries(openspace-module-globebrowsing ${GDAL_LIBRARY})
mark_as_advanced(GDAL_CONFIG GDAL_INCLUDE_DIR GDAL_LIBRARY)
mark_as_advanced(GDAL_CONFIG GDAL_INCLUDE_DIR GDAL_LIBRARY)
endif () # WIN32
target_compile_definitions(openspace-module-globebrowsing PUBLIC GLOBEBROWSING_USE_GDAL)
endif () # OPENSPACE_MODULE_GLOBEBROWSING_USE_GDAL
endif () # WIN32

View File

@@ -1,83 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/cache/texturecontainer.h>
namespace openspace::globebrowsing::cache {
TextureContainer::TextureContainer(TileTextureInitData initData, size_t numTextures)
: _initData(std::move(initData))
, _numTextures(numTextures)
{
reset();
}
void TextureContainer::reset() {
_textures.clear();
_freeTexture = 0;
for (size_t i = 0; i < _numTextures; ++i) {
using namespace ghoul::opengl;
std::unique_ptr<Texture> tex = std::make_unique<Texture>(
_initData.dimensions(),
_initData.ghoulTextureFormat(),
_initData.glTextureFormat(),
_initData.glType(),
Texture::FilterMode::Linear,
Texture::WrappingMode::ClampToEdge,
Texture::AllocateData(_initData.shouldAllocateDataOnCPU())
);
tex->setDataOwnership(Texture::TakeOwnership::Yes);
tex->uploadTexture();
tex->setFilter(Texture::FilterMode::AnisotropicMipMap);
_textures.push_back(std::move(tex));
}
}
void TextureContainer::reset(size_t numTextures) {
_numTextures = numTextures;
reset();
}
ghoul::opengl::Texture* TextureContainer::getTextureIfFree() {
if (_freeTexture < _textures.size()) {
ghoul::opengl::Texture* texture = _textures[_freeTexture].get();
_freeTexture++;
return texture;
}
else {
return nullptr;
}
}
const TileTextureInitData& TextureContainer::tileTextureInitData() const {
return _initData;
}
size_t TextureContainer::size() const {
return _textures.size();
}
} // namespace openspace::globebrowsing::cache

View File

@@ -1,76 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___TEXTURE_CONTAINER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TEXTURE_CONTAINER___H__
#include <modules/globebrowsing/tile/tiletextureinitdata.h>
#include <memory>
#include <vector>
namespace openspace::globebrowsing::cache {
/**
* Owner of texture data used for tiles. Instead of dynamically allocating textures one
* by one, they are created once and reused.
*/
class TextureContainer {
public:
/**
* \param initData is the description of the texture type.
* \param numTextures is the number of textures to allocate.
*/
TextureContainer(TileTextureInitData initData, size_t numTextures);
~TextureContainer() = default;
void reset();
void reset(size_t numTextures);
/**
* \return A pointer to a texture if there is one texture never used before. If there
* are no textures left, nullptr is returned. TextureContainer still owns the
* texture so no delete should be called on the raw pointer.
*/
ghoul::opengl::Texture* getTextureIfFree();
const TileTextureInitData& tileTextureInitData() const;
/**
* \returns the number of textures in this TextureContainer
*/
size_t size() const;
private:
std::vector<std::unique_ptr<ghoul::opengl::Texture>> _textures;
const TileTextureInitData _initData;
size_t _freeTexture = 0;
size_t _numTextures;
};
} // namespace openspace::globebrowsing::cache
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TEXTURE_CONTAINER___H__

View File

@@ -1,227 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/chunk/chunk.h>
#include <modules/globebrowsing/geometry/geodetic3.h>
#include <modules/globebrowsing/globes/renderableglobe.h>
#include <modules/globebrowsing/globes/chunkedlodglobe.h>
#include <modules/globebrowsing/rendering/layer/layergroup.h>
#include <modules/globebrowsing/rendering/layer/layermanager.h>
#include <modules/globebrowsing/tile/chunktile.h>
#include <modules/globebrowsing/tile/tileselector.h>
#include <modules/globebrowsing/tile/tilemetadata.h>
#include <modules/globebrowsing/rendering/layer/layerrendersettings.h>
#include <openspace/util/updatestructures.h>
namespace openspace::globebrowsing {
Chunk::Chunk(const RenderableGlobe& owner, const TileIndex& tileIndex, bool initVisible)
: _owner(owner)
, _tileIndex(tileIndex)
, _isVisible(initVisible)
, _surfacePatch(tileIndex)
{}
const GeodeticPatch& Chunk::surfacePatch() const {
return _surfacePatch;
}
const RenderableGlobe& Chunk::owner() const {
return _owner;
}
const TileIndex Chunk::tileIndex() const {
return _tileIndex;
}
bool Chunk::isVisible() const {
return _isVisible;
}
Chunk::Status Chunk::update(const RenderData& data) {
const std::shared_ptr<const Camera>& savedCamera = _owner.savedCamera();
const Camera& camRef = savedCamera ? *savedCamera : data.camera;
RenderData myRenderData = {
camRef,
data.position,
data.time,
data.doPerformanceMeasurement,
data.renderBinMask,
data.modelTransform
};
_isVisible = true;
if (_owner.chunkedLodGlobe()->testIfCullable(*this, myRenderData)) {
_isVisible = false;
return Status::WantMerge;
}
const int desiredLevel = _owner.chunkedLodGlobe()->desiredLevel(
*this,
myRenderData
);
if (desiredLevel < _tileIndex.level) {
return Status::WantMerge;
}
else if (_tileIndex.level < desiredLevel) {
return Status::WantSplit;
}
else {
return Status::DoNothing;
}
}
Chunk::BoundingHeights Chunk::boundingHeights() const {
using ChunkTileSettingsPair = std::pair<ChunkTile, const LayerRenderSettings*>;
BoundingHeights boundingHeights { 0.f, 0.f, false };
// In the future, this should be abstracted away and more easily queryable.
// One must also handle how to sample pick one out of multiplte heightmaps
std::shared_ptr<LayerManager> lm = owner().chunkedLodGlobe()->layerManager();
// The raster of a height map is the first one. We assume that the height map is
// a single raster image. If it is not we will just use the first raster
// (that is channel 0).
const size_t HeightChannel = 0;
const LayerGroup& heightmaps = lm->layerGroup(layergroupid::GroupID::HeightLayers);
std::vector<ChunkTileSettingsPair> chunkTileSettingPairs =
tileselector::getTilesAndSettingsUnsorted(heightmaps, _tileIndex);
bool lastHadMissingData = true;
for (const ChunkTileSettingsPair& chunkTileSettingsPair : chunkTileSettingPairs) {
const ChunkTile& chunkTile = chunkTileSettingsPair.first;
const LayerRenderSettings* settings = chunkTileSettingsPair.second;
const bool goodTile = (chunkTile.tile.status() == Tile::Status::OK);
const bool hasTileMetaData = (chunkTile.tile.metaData() != nullptr);
if (goodTile && hasTileMetaData) {
TileMetaData* tileMetaData = chunkTile.tile.metaData();
const float minValue = settings->performLayerSettings(
tileMetaData->minValues[HeightChannel]
);
const float maxValue = settings->performLayerSettings(
tileMetaData->maxValues[HeightChannel]
);
if (!boundingHeights.available) {
if (tileMetaData->hasMissingData[HeightChannel]) {
boundingHeights.min = std::min(DefaultHeight, minValue);
boundingHeights.max = std::max(DefaultHeight, maxValue);
}
else {
boundingHeights.min = minValue;
boundingHeights.max = maxValue;
}
boundingHeights.available = true;
}
else {
boundingHeights.min = std::min(boundingHeights.min, minValue);
boundingHeights.max = std::max(boundingHeights.max, maxValue);
}
lastHadMissingData = tileMetaData->hasMissingData[HeightChannel];
}
// Allow for early termination
if (!lastHadMissingData) {
break;
}
}
return boundingHeights;
}
std::vector<glm::dvec4> Chunk::boundingPolyhedronCorners() const {
const Ellipsoid& ellipsoid = owner().ellipsoid();
const GeodeticPatch& patch = surfacePatch();
const BoundingHeights& boundingHeight = boundingHeights();
// assume worst case
const double patchCenterRadius = ellipsoid.maximumRadius();
const double maxCenterRadius = patchCenterRadius + boundingHeight.max;
Geodetic2 halfSize = patch.halfSize();
// As the patch is curved, the maximum height offsets at the corners must be long
// enough to cover large enough to cover a boundingHeight.max at the center of the
// patch.
// Approximating scaleToCoverCenter by assuming the latitude and longitude angles
// of "halfSize" are equal to the angles they create from the center of the
// globe to the patch corners. This is true for the longitude direction when
// the ellipsoid can be approximated as a sphere and for the latitude for patches
// close to the equator. Close to the pole this will lead to a bigger than needed
// value for scaleToCoverCenter. However, this is a simple calculation and a good
// Approximation.
const double y1 = tan(halfSize.lat);
const double y2 = tan(halfSize.lon);
const double scaleToCoverCenter = sqrt(1 + pow(y1, 2) + pow(y2, 2));
const double maxCornerHeight = maxCenterRadius * scaleToCoverCenter -
patchCenterRadius;
const bool chunkIsNorthOfEquator = patch.isNorthern();
// The minimum height offset, however, we can simply
const double minCornerHeight = boundingHeight.min;
std::vector<glm::dvec4> corners(8);
const double latCloseToEquator = patch.edgeLatitudeNearestEquator();
const Geodetic3 p1Geodetic = {
{ latCloseToEquator, patch.minLon() },
maxCornerHeight
};
const Geodetic3 p2Geodetic = {
{ latCloseToEquator, patch.maxLon() },
maxCornerHeight
};
const glm::vec3 p1 = ellipsoid.cartesianPosition(p1Geodetic);
const glm::vec3 p2 = ellipsoid.cartesianPosition(p2Geodetic);
const glm::vec3 p = 0.5f * (p1 + p2);
const Geodetic2 pGeodetic = ellipsoid.cartesianToGeodetic2(p);
const double latDiff = latCloseToEquator - pGeodetic.lat;
for (size_t i = 0; i < 8; ++i) {
const Quad q = static_cast<Quad>(i % 4);
const double cornerHeight = i < 4 ? minCornerHeight : maxCornerHeight;
Geodetic3 cornerGeodetic = { patch.corner(q), cornerHeight };
const bool cornerIsNorthern = !((i / 2) % 2);
const bool cornerCloseToEquator = chunkIsNorthOfEquator ^ cornerIsNorthern;
if (cornerCloseToEquator) {
cornerGeodetic.geodetic2.lat += latDiff;
}
corners[i] = glm::dvec4(ellipsoid.cartesianPosition(cornerGeodetic), 1);
}
return corners;
}
} // namespace openspace::globebrowsing

View File

@@ -1,103 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___CHUNK___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___CHUNK___H__
#include <modules/globebrowsing/geometry/geodeticpatch.h>
#include <modules/globebrowsing/tile/tileindex.h>
#include <ghoul/glm.h>
#include <vector>
namespace openspace { struct RenderData; }
namespace openspace::globebrowsing {
class RenderableGlobe;
struct TileIndex;
class Chunk {
public:
constexpr static float DefaultHeight = 0.f;
struct BoundingHeights {
float min;
float max;
bool available;
};
enum class Status {
DoNothing,
WantMerge,
WantSplit
};
Chunk(const RenderableGlobe& owner, const TileIndex& tileIndex,
bool initVisible = true);
/**
* Updates the Chunk internally and returns the Status of the Chunk.
*
* Tests if the Chunk is cullable and gets the desired level of the Chunk. If the
* Chunk is cullable it will be set to invisible and return Status::WANT_MERGE.
* If the desired level is smaller than the current level of the chunk it will
* return Status::WANT_MERGE, if it is larger it will return Status::WANT_SPLIT,
* otherwise Status::DO_NOTHING.
*
* \return The Status of the chunk.
*/
Status update(const RenderData& data);
/**
* Returns a convex polyhedron of eight vertices tightly bounding the volume of
* the Chunk.
*/
std::vector<glm::dvec4> boundingPolyhedronCorners() const;
const GeodeticPatch& surfacePatch() const;
const RenderableGlobe& owner() const;
const TileIndex tileIndex() const;
bool isVisible() const;
/**
* Returns BoundingHeights that fits the Chunk as tightly as possible.
*
* If the Chunk uses more than one HightLayer, the BoundingHeights will be set
* to cover all HeightLayers. If the Chunk has a higher level than its highest
* resolution HightLayer Tile, it will base its BoundingHeights on that Tile.
* This means that high level Chunks can have BoundingHeights that are not
* tightly fitting.
*/
BoundingHeights boundingHeights() const;
private:
const RenderableGlobe& _owner;
const TileIndex _tileIndex;
bool _isVisible;
const GeodeticPatch _surfacePatch;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___CHUNK___H__

View File

@@ -1,57 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/chunk/chunklevelevaluator/availabletiledataevaluator.h>
#include <modules/globebrowsing/chunk/chunk.h>
#include <modules/globebrowsing/globes/chunkedlodglobe.h>
#include <modules/globebrowsing/globes/renderableglobe.h>
#include <modules/globebrowsing/rendering/layer/layer.h>
#include <modules/globebrowsing/rendering/layer/layergroup.h>
#include <modules/globebrowsing/rendering/layer/layermanager.h>
#include <modules/globebrowsing/tile/tile.h>
namespace openspace::globebrowsing::chunklevelevaluator {
int AvailableTileData::desiredLevel(const Chunk& chunk, const RenderData&) const {
std::shared_ptr<LayerManager> layerManager =
chunk.owner().chunkedLodGlobe()->layerManager();
const int currLevel = chunk.tileIndex().level;
for (size_t i = 0; i < layergroupid::NUM_LAYER_GROUPS; ++i) {
for (const std::shared_ptr<Layer>& layer :
layerManager->layerGroup(i).activeLayers())
{
Tile::Status status = layer->tileStatus(chunk.tileIndex());
if (status == Tile::Status::OK) {
return UnknownDesiredLevel;
}
}
}
return currLevel - 1;
}
} // namespace openspace::globebrowsing::chunklevelevaluator

View File

@@ -1,45 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___AVAILABLETILEDATAEVALUATOR___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___AVAILABLETILEDATAEVALUATOR___H__
#include <modules/globebrowsing/chunk/chunklevelevaluator/chunklevelevaluator.h>
namespace openspace::globebrowsing::chunklevelevaluator {
/**
* If this chunk has available tile data for any LayerGroup on any of its active
* Layers it will return an UNKNOWN_DESIRED_LEVEL. If no data is available it will
* evaluate to a level that is <code>current level -1</code>.
*/
class AvailableTileData : public Evaluator {
public:
virtual ~AvailableTileData() override = default;
int desiredLevel(const Chunk& chunk, const RenderData& data) const override;
};
} // namespace openspace::globebrowsing::chunklevelevaluator
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___AVAILABLETILEDATAEVALUATOR___H__

View File

@@ -1,49 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___CHUNKLEVELEVALUATOR___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___CHUNKLEVELEVALUATOR___H__
namespace openspace { struct RenderData; }
namespace openspace::globebrowsing { class Chunk; }
namespace openspace::globebrowsing::chunklevelevaluator {
/**
* Abstract class defining an interface for accessing a desired level of a Chunk.
* The desired level can be used in the process of determining whether a Chunk should
* want to split, merge or do nothing.
*/
class Evaluator {
public:
virtual ~Evaluator() = default;
constexpr static const int UnknownDesiredLevel = -1;
virtual int desiredLevel(const Chunk& chunk, const RenderData& data) const = 0;
};
} // namespace openspace::globebrowsing::chunklevelevaluator
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___CHUNKLEVELEVALUATOR___H__

View File

@@ -1,70 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/chunk/chunklevelevaluator/distanceevaluator.h>
#include <modules/globebrowsing/chunk/chunk.h>
#include <modules/globebrowsing/globes/chunkedlodglobe.h>
#include <modules/globebrowsing/globes/renderableglobe.h>
#include <openspace/util/updatestructures.h>
namespace openspace::globebrowsing::chunklevelevaluator {
int Distance::desiredLevel(const Chunk& chunk, const RenderData& data) const {
// Calculations are done in the reference frame of the globe
// (model space). Hence, the camera position needs to be transformed
// with the inverse model matrix
const glm::dmat4 inverseModelTransform = chunk.owner().inverseModelTransform();
const RenderableGlobe& globe = chunk.owner();
const Ellipsoid& ellipsoid = globe.ellipsoid();
const glm::dvec3 cameraPosition = glm::dvec3(inverseModelTransform *
glm::dvec4(data.camera.positionVec3(), 1.0));
const Geodetic2 pointOnPatch = chunk.surfacePatch().closestPoint(
ellipsoid.cartesianToGeodetic2(cameraPosition)
);
const glm::dvec3 patchNormal = ellipsoid.geodeticSurfaceNormal(pointOnPatch);
glm::dvec3 patchPosition = ellipsoid.cartesianSurfacePosition(pointOnPatch);
const Chunk::BoundingHeights heights = chunk.boundingHeights();
const double heightToChunk = heights.min;
// Offset position according to height
patchPosition += patchNormal * heightToChunk;
const glm::dvec3 cameraToChunk = patchPosition - cameraPosition;
// Calculate desired level based on distance
const double distanceToPatch = glm::length(cameraToChunk);
const double distance = distanceToPatch;
const double scaleFactor = globe.generalProperties().lodScaleFactor *
ellipsoid.minimumRadius();
const double projectedScaleFactor = scaleFactor / distance;
const int desiredLevel = static_cast<int>(ceil(log2(projectedScaleFactor)));
return desiredLevel;
}
} // namespace openspace::globebrowsing::chunklevelevaluator

View File

@@ -1,44 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___DISTANCEEVALUATOR___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___DISTANCEEVALUATOR___H__
#include <modules/globebrowsing/chunk/chunklevelevaluator/chunklevelevaluator.h>
namespace openspace::globebrowsing::chunklevelevaluator {
/**
* Evaluate the Chunk level depending on the distance from the Camera to the Chunk.
* This evaluation method aims to keep the screen size (horizontal length and not
* area) of all chunks constant.
*/
class Distance : public Evaluator {
public:
int desiredLevel(const Chunk& chunk, const RenderData& data) const override;
};
} // namespace openspace::globebrowsing::chunklevelevaluator
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___DISTANCEEVALUATOR___H__

View File

@@ -1,129 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/chunk/chunklevelevaluator/projectedareaevaluator.h>
#include <modules/globebrowsing/chunk/chunk.h>
#include <modules/globebrowsing/geometry/geodetic3.h>
#include <modules/globebrowsing/globes/chunkedlodglobe.h>
#include <modules/globebrowsing/globes/renderableglobe.h>
#include <modules/globebrowsing/rendering/layer/layermanager.h>
#include <modules/globebrowsing/tile/tileprovider/tileprovider.h>
#include <openspace/util/updatestructures.h>
namespace openspace::globebrowsing::chunklevelevaluator {
int ProjectedArea::desiredLevel(const Chunk& chunk, const RenderData& data) const {
// Calculations are done in the reference frame of the globe
// (model space). Hence, the camera position needs to be transformed
// with the inverse model matrix
const glm::dmat4 inverseModelTransform = chunk.owner().inverseModelTransform();
const RenderableGlobe& globe = chunk.owner();
const Ellipsoid& ellipsoid = globe.ellipsoid();
const glm::dvec4 cameraPositionModelSpace = glm::dvec4(data.camera.positionVec3(), 1);
const glm::dvec3 cameraPosition = glm::dvec3(
inverseModelTransform * cameraPositionModelSpace
);
const glm::dvec3 cameraToEllipsoidCenter = -cameraPosition;
const Geodetic2 cameraGeodeticPos = ellipsoid.cartesianToGeodetic2(cameraPosition);
// Approach:
// The projected area of the chunk will be calculated based on a small area that
// is close to the camera, and the scaled up to represent the full area.
// The advantage of doing this is that it will better handle the cases where the
// full patch is very curved (e.g. stretches from latitude 0 to 90 deg).
const Geodetic2 center = chunk.surfacePatch().center();
const Geodetic2 closestCorner = chunk.surfacePatch().closestCorner(cameraGeodeticPos);
// Camera
// |
// V
//
// oo
// [ ]<
// *geodetic space*
//
// closestCorner
// +-----------------+ <-- north east corner
// | |
// | center |
// | |
// +-----------------+ <-- south east corner
const Chunk::BoundingHeights heights = chunk.boundingHeights();
const Geodetic3 c = { center, heights.min };
const Geodetic3 c1 = { Geodetic2(center.lat, closestCorner.lon), heights.min };
const Geodetic3 c2 = { Geodetic2(closestCorner.lat, center.lon), heights.min };
// Camera
// |
// V
//
// oo
// [ ]<
// *geodetic space*
//
// +--------c2-------+ <-- north east corner
// | |
// c1 c |
// | |
// +-----------------+ <-- south east corner
// Go from geodetic to cartesian space and project onto unit sphere
const glm::dvec3 A = glm::normalize(
cameraToEllipsoidCenter + ellipsoid.cartesianPosition(c)
);
const glm::dvec3 B = glm::normalize(
cameraToEllipsoidCenter + ellipsoid.cartesianPosition(c1)
);
const glm::dvec3 C = glm::normalize(
cameraToEllipsoidCenter + ellipsoid.cartesianPosition(c2)
);
// Camera *cartesian space*
// | +--------+---+
// V __--'' __--'' /
// C-------A--------- +
// oo / / /
//[ ]< +-------B----------+
//
// If the geodetic patch is small (i.e. has small width), that means the patch in
// cartesian space will be almost flat, and in turn, the triangle ABC will roughly
// correspond to 1/8 of the full area
const glm::dvec3 AB = B - A;
const glm::dvec3 AC = C - A;
const double areaABC = 0.5 * glm::length(glm::cross(AC, AB));
const double projectedChunkAreaApprox = 8 * areaABC;
const double scaledArea = globe.generalProperties().lodScaleFactor *
projectedChunkAreaApprox;
return chunk.tileIndex().level + static_cast<int>(round(scaledArea - 1));
}
} // namespace openspace::globebrowsing::chunklevelevaluator

View File

@@ -1,46 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___PROJECTEDAREAEVALUATOR___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___PROJECTEDAREAEVALUATOR___H__
#include <modules/globebrowsing/chunk/chunklevelevaluator/chunklevelevaluator.h>
namespace openspace::globebrowsing::chunklevelevaluator {
/**
* Evaluate the chunk level using the area of the non-heightmapped Chunk projected
* on a sphere with the center in the position of the camera. A Chunk near the
* horizon will have a small projected area and hence a lower desired level. This
* evaluation is more forgiving than EvaluateChunkLevelByDistance, meaning it results
* in lower desired levels.
*/
class ProjectedArea : public Evaluator {
public:
virtual int desiredLevel(const Chunk& chunk, const RenderData& data) const override;
};
} // namespace openspace::globebrowsing::chunklevelevaluator
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___PROJECTEDAREAEVALUATOR___H__

View File

@@ -1,187 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/chunk/chunknode.h>
#include <ghoul/misc/assert.h>
#include <stack>
#include <queue>
namespace openspace::globebrowsing {
ChunkNode::ChunkNode(Chunk chunk, ChunkNode* parent)
: _parent(parent)
, _children({ {nullptr, nullptr, nullptr, nullptr} })
, _chunk(std::move(chunk))
{}
bool ChunkNode::isRoot() const {
return _parent == nullptr;
}
bool ChunkNode::isLeaf() const {
return _children[0] == nullptr;
}
bool ChunkNode::updateChunkTree(const RenderData& data) {
if (isLeaf()) {
Chunk::Status status = _chunk.update(data);
if (status == Chunk::Status::WantSplit) {
split();
}
return status == Chunk::Status::WantMerge;
}
else {
char requestedMergeMask = 0;
for (int i = 0; i < 4; ++i) {
if (_children[i]->updateChunkTree(data)) {
requestedMergeMask |= (1 << i);
}
}
const bool allChildrenWantsMerge = requestedMergeMask == 0xf;
const bool thisChunkWantsSplit = _chunk.update(data) == Chunk::Status::WantSplit;
if (allChildrenWantsMerge && !thisChunkWantsSplit) {
merge();
}
return false;
}
}
void ChunkNode::depthFirst(const std::function<void(const ChunkNode&)>& f) const {
f(*this);
if (!isLeaf()) {
for (int i = 0; i < 4; ++i) {
_children[i]->depthFirst(f);
}
}
}
void ChunkNode::breadthFirst(const std::function<void(const ChunkNode&)>& f) const {
std::queue<const ChunkNode*> Q;
// Loop through nodes in breadths first order
Q.push(this);
while (!Q.empty()) {
const ChunkNode* node = Q.front();
Q.pop();
f(*node);
// Add children to queue, if any
if (!node->isLeaf()) {
for (int i = 0; i < 4; ++i) {
Q.push(node->_children[i].get());
}
}
}
}
void ChunkNode::reverseBreadthFirst(const std::function<void(const ChunkNode&)>& f) const
{
std::stack<const ChunkNode*> S;
std::queue<const ChunkNode*> Q;
// Loop through nodes in breadths first order
Q.push(this);
while (!Q.empty()) {
const ChunkNode* node = Q.front();
Q.pop();
// Add node to future stack
S.push(node);
// Add children to queue, if any
if (!node->isLeaf()) {
for (const auto& c : node->_children) {
Q.push(c.get());
}
//for (int i = 0; i < 4; ++i) {
// Q.push(node->_children[i].get());
//}
}
}
// Loop through all nodes in stack, this will be reversed breadth first
while (!S.empty()) {
f(*S.top());
S.pop();
}
}
const ChunkNode& ChunkNode::find(const Geodetic2& location) const {
const ChunkNode* node = this;
while (!node->isLeaf()) {
const Geodetic2 center = node->_chunk.surfacePatch().center();
int index = 0;
if (center.lon < location.lon) {
++index;
}
if (location.lat < center.lat) {
++index;
++index;
}
node = &(node->child(static_cast<Quad>(index)));
}
return *node;
}
const ChunkNode& ChunkNode::child(const Quad& quad) const {
return *_children[quad];
}
void ChunkNode::split(int depth) {
if (depth > 0 && isLeaf()) {
for (size_t i = 0; i < _children.size(); ++i) {
Chunk chunk(_chunk.owner(), _chunk.tileIndex().child(static_cast<Quad>(i)));
_children[i] = std::make_unique<ChunkNode>(chunk, this);
}
}
if (depth - 1 > 0) {
for (const std::unique_ptr<ChunkNode>& child : _children) {
child->split(depth - 1);
}
}
}
void ChunkNode::merge() {
for (std::unique_ptr<ChunkNode>& child : _children) {
if (child) {
child->merge();
}
child = nullptr;
}
ghoul_assert(isLeaf(), "ChunkNode must be leaf after merge");
}
const Chunk& ChunkNode::chunk() const {
return _chunk;
}
} // namespace openspace::globebrowsing

View File

@@ -1,84 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___CHUNKNODE___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___CHUNKNODE___H__
#include <modules/globebrowsing/chunk/chunk.h>
#include <array>
#include <functional>
#include <memory>
namespace openspace::globebrowsing {
class ChunkedLodGlobe;
class ChunkNode {
public:
ChunkNode(Chunk chunk, ChunkNode* parent = nullptr);
/**
* Recursively split the ChunkNode.
*
* \param depth defines how deep the recursion should go. If depth == 1 (default),
* the ChunkNode will only split once.
*/
void split(int depth = 1);
/**
* Deletes all children of the ChunkNode recursively.
*/
void merge();
bool isRoot() const;
bool isLeaf() const;
void depthFirst(const std::function<void(const ChunkNode&)>& f) const;
void breadthFirst(const std::function<void(const ChunkNode&)>& f) const;
void reverseBreadthFirst(const std::function<void(const ChunkNode&)>& f) const;
const ChunkNode& find(const Geodetic2& location) const;
const ChunkNode& child(const Quad& quad) const;
const Chunk& chunk() const;
/**
* Updates all children recursively. If this ChunkNode wants to split it will,
* otherwise check if the children wants to merge. If all children wants to merge
* and the Status of this Chunk is not Status::WANT_SPLIT it will merge.
*
* \returns true if the ChunkNode can merge and false if it can not merge.
*/
bool updateChunkTree(const RenderData& data);
private:
ChunkNode* _parent;
std::array<std::unique_ptr<ChunkNode>, 4> _children;
Chunk _chunk;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___CHUNKNODE___H__

View File

@@ -1,47 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___CHUNKCULLER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___CHUNKCULLER___H__
namespace openspace { struct RenderData; }
namespace openspace::globebrowsing { class Chunk; }
namespace openspace::globebrowsing::culling {
class ChunkCuller {
public:
virtual ~ChunkCuller() = default;
/**
* Determine if the Chunk is cullable. That is return true if removing the
* Chunk 'culling it' will not have any result on the final rendering. Culling
* it will make the rendering faster.
*/
virtual bool isCullable(const Chunk& chunk, const RenderData& renderData) = 0;
};
} // namespace openspace::globebrowsing::culling
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___CHUNKCULLER___H__

View File

@@ -1,61 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/chunk/culling/frustumculler.h>
#include <modules/globebrowsing/chunk/chunk.h>
#include <modules/globebrowsing/globes/renderableglobe.h>
#include <openspace/util/updatestructures.h>
namespace openspace::globebrowsing::culling {
FrustumCuller::FrustumCuller(AABB3 viewFrustum)
: _viewFrustum(std::move(viewFrustum))
{}
bool FrustumCuller::isCullable(const Chunk& chunk, const RenderData& renderData) {
// Calculate the MVP matrix
const glm::dmat4 modelTransform = chunk.owner().modelTransform();
const glm::dmat4 viewTransform = glm::dmat4(renderData.camera.combinedViewMatrix());
const glm::dmat4 modelViewProjectionTransform = glm::dmat4(
renderData.camera.sgctInternal.projectionMatrix()
) * viewTransform * modelTransform;
const std::vector<glm::dvec4>& corners = chunk.boundingPolyhedronCorners();
// Create a bounding box that fits the patch corners
AABB3 bounds; // in screen space
for (size_t i = 0; i < 8; ++i) {
const glm::dvec4 cornerClippingSpace = modelViewProjectionTransform * corners[i];
const glm::dvec3 ndc = glm::dvec3(
(1.f / glm::abs(cornerClippingSpace.w)) * cornerClippingSpace
);
bounds.expand(ndc);
}
return !(_viewFrustum.intersects(bounds));
}
} // namespace openspace::globebrowsing::culling

View File

@@ -1,59 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___FRUSTUMCULLER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___FRUSTUMCULLER___H__
#include <modules/globebrowsing/chunk/culling/chunkculler.h>
#include <modules/globebrowsing/geometry/aabb.h>
namespace openspace::globebrowsing::culling {
/**
* Culls all chunks that are completely outside the view frustum.
*
* The frustum culling uses a 2D axis aligned bounding box for the Chunk in
* screen space. This is calculated from a bounding polyhedron bounding the
* Chunk. Hence the culling will not be 'perfect' but fast and good enough for
* culling chunks outside the frustum with some margin.
*/
class FrustumCuller : public ChunkCuller {
public:
virtual ~FrustumCuller() override = default;
/**
* \param viewFrustum is the view space in normalized device coordinates space.
* Hence it is an axis aligned bounding box and not a real frustum.
*/
FrustumCuller(AABB3 viewFrustum);
bool isCullable(const Chunk& chunk, const RenderData& renderData) override;
private:
const AABB3 _viewFrustum;
};
} // namespace openspace::globebrowsing::culling
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___FRUSTUMCULLER___H__

View File

@@ -1,108 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/chunk/culling/horizonculler.h>
#include <modules/globebrowsing/chunk/chunk.h>
#include <modules/globebrowsing/globes/renderableglobe.h>
#include <openspace/util/updatestructures.h>
#include <array>
namespace openspace::globebrowsing::culling {
bool HorizonCuller::isCullable(const Chunk& chunk, const RenderData& renderData) {
// Calculations are done in the reference frame of the globe. Hence, the camera
// position needs to be transformed with the inverse model matrix
const glm::dmat4 inverseModelTransform = chunk.owner().inverseModelTransform();
const Ellipsoid& ellipsoid = chunk.owner().ellipsoid();
const GeodeticPatch& patch = chunk.surfacePatch();
const float maxHeight = chunk.boundingHeights().max;
const glm::dvec3 globePos = glm::dvec3(0,0,0); // In model space it is 0
const double minimumGlobeRadius = ellipsoid.minimumRadius();
const glm::dvec3 cameraPos = glm::dvec3(
inverseModelTransform * glm::dvec4(renderData.camera.positionVec3(), 1)
);
const glm::dvec3 globeToCamera = cameraPos;
const Geodetic2 cameraPositionOnGlobe = ellipsoid.cartesianToGeodetic2(globeToCamera);
const Geodetic2 closestPatchPoint = patch.closestPoint(cameraPositionOnGlobe);
glm::dvec3 objectPos = ellipsoid.cartesianSurfacePosition(closestPatchPoint);
// objectPosition is closest in latlon space but not guaranteed to be closest in
// castesian coordinates. Therefore we compare it to the corners and pick the
// real closest point,
std::array<glm::dvec3, 4> corners = {
ellipsoid.cartesianSurfacePosition(chunk.surfacePatch().corner(NORTH_WEST)),
ellipsoid.cartesianSurfacePosition(chunk.surfacePatch().corner(NORTH_EAST)),
ellipsoid.cartesianSurfacePosition(chunk.surfacePatch().corner(SOUTH_WEST)),
ellipsoid.cartesianSurfacePosition(chunk.surfacePatch().corner(SOUTH_EAST))
};
for (int i = 0; i < 4; ++i) {
const double distance = glm::length(cameraPos - corners[i]);
if (distance < glm::length(cameraPos - objectPos)) {
objectPos = corners[i];
}
}
return isCullable(cameraPos, globePos, objectPos, maxHeight, minimumGlobeRadius);
}
bool HorizonCuller::isCullable(const glm::dvec3& cameraPosition,
const glm::dvec3& globePosition,
const glm::dvec3& objectPosition,
double objectBoundingSphereRadius,
double minimumGlobeRadius)
{
const double objectP = pow(length(objectPosition - globePosition), 2);
const double horizonP = pow(minimumGlobeRadius - objectBoundingSphereRadius, 2);
if (objectP < horizonP) {
return false;
}
const double cameraP = pow(length(cameraPosition - globePosition), 2);
const double minR = pow(minimumGlobeRadius, 2);
if (cameraP < minR) {
return false;
}
const double minimumAllowedDistanceToObjectFromHorizon = sqrt(objectP - horizonP);
const double distanceToHorizon = sqrt(cameraP - minR);
// Minimum allowed for the object to be occluded
const double minimumAllowedDistanceToObjectSquared =
pow(distanceToHorizon + minimumAllowedDistanceToObjectFromHorizon, 2) +
pow(objectBoundingSphereRadius, 2);
const double distanceToObjectSquared = pow(
length(objectPosition - cameraPosition),
2
);
return distanceToObjectSquared > minimumAllowedDistanceToObjectSquared;
}
} // namespace openspace::globebrowsing::culling

View File

@@ -1,53 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___HORIZONCULLER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___HORIZONCULLER___H__
#include <modules/globebrowsing/chunk/culling/chunkculler.h>
#include <ghoul/glm.h>
namespace openspace::globebrowsing::culling {
/**
* In this implementation of the horizon culling, the closer the ellipsoid is to a
* sphere, the better this will make the culling. Using the minimum radius to
* be safe. This means that if the ellipsoid has high difference between radii,
* splitting might accur even though it may not be needed.
*/
class HorizonCuller : public ChunkCuller {
public:
virtual ~HorizonCuller() override = default;
bool isCullable(const Chunk& chunk, const RenderData& renderData) override;
private:
bool isCullable(const glm::dvec3& cameraPosition, const glm::dvec3& globePosition,
const glm::dvec3& objectPosition, double objectBoundingSphereRadius,
double minimumGlobeRadius);
};
} // namespace openspace::globebrowsing::culling
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___HORIZONCULLER___H__

View File

@@ -1,169 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/geometry/aabb.h>
#include <limits>
namespace openspace::globebrowsing {
AABB1::AABB1(float minValue, float maxValue)
: min(minValue)
, max(maxValue)
{}
void AABB1::expand(float p) {
min = glm::min(min, p);
max = glm::max(max, p);
}
float AABB1::center() const {
return 0.5f * (min + max);
}
float AABB1::size() const {
return max - min;
}
bool AABB1::contains(float p) const {
return (min <= p) && (p <= max);
}
bool AABB1::contains(const AABB1& o) const {
return (min <= o.min) && (o.max <= max);
}
bool AABB1::intersects(const AABB1& o) const {
return (min <= o.max) && (o.min <= max);
}
AABB1::AABBSpatialRelation AABB1::relationTo(const AABB1& o) const {
if (intersects(o)) {
if (contains(o)) {
return AABB1::AABBSpatialRelation::Containing;
}
if (o.contains(*this)) {
return AABB1::AABBSpatialRelation::Contained;
}
return AABB1::AABBSpatialRelation::Intersecting;
}
return AABB1::AABBSpatialRelation::None;
}
AABB2::AABB2(glm::vec2 minValue, glm::vec2 maxValue)
: min(std::move(minValue))
, max(std::move(maxValue))
{}
void AABB2::expand(const glm::vec2& p) {
min = glm::min(min, p);
max = glm::max(max, p);
}
glm::vec2 AABB2::center() const {
return 0.5f * (min + max);
}
glm::vec2 AABB2::size() const {
return max - min;
}
bool AABB2::contains(const glm::vec2& p) const {
return (min.x <= p.x) && (p.x <= max.x)
&& (min.y <= p.y) && (p.y <= max.y);
}
bool AABB2::contains(const AABB2& o) const {
return (min.x <= o.min.x) && (o.max.x <= max.x)
&& (min.y <= o.min.y) && (o.max.y <= max.y);
}
bool AABB2::intersects(const AABB2& o) const {
return (min.x <= o.max.x) && (o.min.x <= max.x)
&& (min.y <= o.max.y) && (o.min.y <= max.y);
}
AABB2::AABBSpatialRelation AABB2::relationTo(const AABB2& o) const {
if (intersects(o)) {
if (contains(o)) {
return AABB2::AABBSpatialRelation::Containing;
}
if (o.contains(*this)) {
return AABB2::AABBSpatialRelation::Contained;
}
return AABB2::AABBSpatialRelation::Intersecting;
}
return AABB2::AABBSpatialRelation::None;
}
AABB3::AABB3(glm::vec3 minValue, glm::vec3 maxValue)
: min(std::move(minValue))
, max(std::move(maxValue))
{}
void AABB3::expand(glm::vec3 p) {
min = glm::min(min, p);
max = glm::max(max, p);
}
glm::vec3 AABB3::center() const {
return 0.5f * (min + max);
}
glm::vec3 AABB3::size() const {
return max - min;
}
bool AABB3::contains(const glm::vec3& p) const {
return (min.x <= p.x) && (p.x <= max.x)
&& (min.y <= p.y) && (p.y <= max.y)
&& (min.z <= p.z) && (p.z <= max.z);
}
bool AABB3::contains(const AABB3& o) const {
return (min.x <= o.min.x) && (o.max.x <= max.x)
&& (min.y <= o.min.y) && (o.max.y <= max.y)
&& (min.z <= o.min.z) && (o.max.z <= max.z);
}
bool AABB3::intersects(const AABB3& o) const {
return (min.x <= o.max.x) && (o.min.x <= max.x)
&& (min.y <= o.max.y) && (o.min.y <= max.y)
&& (min.z <= o.max.z) && (o.min.z <= max.z);
}
AABB3::AABBSpatialRelation AABB3::relationTo(const AABB3& o) const {
if (intersects(o)) {
if (contains(o)) {
return AABB3::AABBSpatialRelation::Containing;
}
if (o.contains(*this)) {
return AABB3::AABBSpatialRelation::Contained;
}
return AABB3::AABBSpatialRelation::Intersecting;
}
return AABB3::AABBSpatialRelation::None;
}
} // namespace openspace::globebrowsing

View File

@@ -1,103 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___AABB___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___AABB___H__
#include <ghoul/glm.h>
namespace openspace::globebrowsing {
struct AABB1 {
enum class AABBSpatialRelation {
None,
Intersecting,
Contained,
Containing
};
AABB1(float minValue = std::numeric_limits<float>::max(),
float maxValue = -std::numeric_limits<float>::max());
void expand(float p);
float center() const;
float size() const;
bool contains(float p) const;
bool contains(const AABB1& o) const;
bool intersects(const AABB1& o) const;
AABBSpatialRelation relationTo(const AABB1& o) const;
float min;
float max;
};
struct AABB2 {
enum class AABBSpatialRelation {
None,
Intersecting,
Contained,
Containing
};
AABB2(glm::vec2 minValue = glm::vec2(std::numeric_limits<float>::max()),
glm::vec2 maxValue = glm::vec2(-std::numeric_limits<float>::max()));
void expand(const glm::vec2& p);
glm::vec2 center() const;
glm::vec2 size() const;
bool contains(const glm::vec2& p) const;
bool contains(const AABB2& o) const;
bool intersects(const AABB2& o) const;
AABBSpatialRelation relationTo(const AABB2& o) const;
glm::vec2 min;
glm::vec2 max;
};
struct AABB3 {
enum class AABBSpatialRelation {
None,
Intersecting,
Contained,
Containing
};
AABB3(glm::vec3 minValue = glm::vec3(std::numeric_limits<float>::max()),
glm::vec3 maxValue = glm::vec3(-std::numeric_limits<float>::max()));
void expand(const glm::vec3 p);
glm::vec3 center() const;
glm::vec3 size() const;
bool contains(const glm::vec3& p) const;
bool contains(const AABB3& o) const;
bool intersects(const AABB3& o) const;
AABBSpatialRelation relationTo(const AABB3& o) const;
glm::vec3 min;
glm::vec3 max;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___AABB___H__

View File

@@ -1,110 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___ANGLE___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___ANGLE___H__
#include <ghoul/glm.h>
#include <memory>
//#include <math.h>
namespace openspace::globebrowsing {
template <typename T>
class Angle {
public:
/** = 0 radians = 0 degrees = no revolution */
static const Angle<T> ZERO;
/** = PI/2 radians = 90 degrees = quarter of a revolution */
static const Angle<T> QUARTER;
/** = PI radians = 180 degrees = half a revolution */
static const Angle<T> HALF;
/** = 2PI radians = 360 degrees = a full revolution */
static const Angle<T> FULL;
static Angle<T> fromRadians(T radians);
static Angle<T> fromDegrees(T degrees);
/** Copy constructor */
Angle<T>(const Angle<T>& other);
public:
inline T asRadians() const;
inline T asDegrees() const;
Angle<T> operator+(const Angle<T>& rhs) const;
Angle<T> operator-(const Angle<T>& rhs) const;
Angle<T> operator*(T rhs) const;
Angle<T> operator/(T rhs) const;
Angle<T> operator-() const;
void operator+=(const Angle<T>& rhs);
void operator-=(const Angle<T>& rhs);
void operator*=(T rhs);
void operator/=(T rhs);
bool operator<(const Angle<T>& rhs) const;
bool operator<=(const Angle<T>& rhs) const;
bool operator>(const Angle<T>& rhs) const;
bool operator>=(const Angle<T>& rhs) const;
bool operator==(const Angle<T>& rhs) const;
bool operator!=(const Angle<T>& rhs) const;
/**
* Normalizes the angle to the interval [0, 2pi[
*/
Angle<T>& normalize();
/**
* Normalizes the angle to the interval [center - pi, center + pi[
*/
Angle<T>& normalizeAround(const Angle<T>& center);
/**
* Clamps the angle to the interval [min, max].
* Default arguments are [0, 2pi].
*/
Angle<T>& clamp(const Angle<T>& min = ZERO, const Angle<T>& max = FULL);
Angle<T> abs() const;
private:
/** Private constructor. Use factory methods to avoid unit confusion */
Angle<T>(T rad);
T _radians;
};
using dAngle = Angle<double>;
using fAngle = Angle<float>;
} // namespace openspace::globebrowsing
#include "angle.inl"
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___ANGLE___H__

View File

@@ -1,205 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/geometry/angle.h>
namespace openspace::globebrowsing {
//////////////////////////////////////////////////////////////////////////////////////////
// STATIC CONSTANTS //
//////////////////////////////////////////////////////////////////////////////////////////
template <typename T>
const Angle<T> Angle<T>::ZERO = Angle<T>(T(0));
template <typename T>
const Angle<T> Angle<T>::QUARTER = Angle<T>(glm::half_pi<T>());
template <typename T>
const Angle<T> Angle<T>::HALF = Angle<T>(glm::pi<T>());
template <typename T>
const Angle<T> Angle<T>::FULL = Angle<T>(glm::two_pi<T>());
//////////////////////////////////////////////////////////////////////////////////////////
// Constructors //
//////////////////////////////////////////////////////////////////////////////////////////
template <typename T>
Angle<T>::Angle(const Angle<T>& other)
: _radians(other._radians)
{}
template <typename T>
Angle<T>::Angle(T radians)
: _radians(radians)
{}
//////////////////////////////////////////////////////////////////////////////////////////
// Factory Methods //
//////////////////////////////////////////////////////////////////////////////////////////
template <typename T>
Angle<T> Angle<T>::fromRadians(T rads) {
return Angle<T>(rads);
}
template <typename T>
Angle<T> Angle<T>::fromDegrees(T degrees) {
return Angle<T>(glm::radians(degrees));
}
//////////////////////////////////////////////////////////////////////////////////////////
// Conversions //
//////////////////////////////////////////////////////////////////////////////////////////
template <typename T>
T Angle<T>::asRadians() const {
return _radians;
}
template <typename T>
T Angle<T>::asDegrees() const {
return glm::degrees(_radians);
}
//////////////////////////////////////////////////////////////////////////////////////////
// Operators //
//////////////////////////////////////////////////////////////////////////////////////////
template <typename T>
Angle<T> Angle<T>::operator+(const Angle<T>& rhs) const{
return Angle<T>(_radians + rhs._radians);
}
template <typename T>
Angle<T> Angle<T>::operator-(const Angle<T>& rhs) const{
return Angle<T>(_radians - rhs._radians);
}
template <typename T>
Angle<T> Angle<T>::operator*(T multiplier) const{
return Angle<T>(_radians * multiplier);
}
template <typename T>
Angle<T> Angle<T>::operator/(T divisor) const{
return Angle<T>(_radians / divisor);
}
template <typename T>
Angle<T> Angle<T>::operator-() const {
return Angle<T>(-_radians);
}
template <typename T>
void Angle<T>::operator+=(const Angle<T>& rhs){
_radians += rhs._radians;
}
template <typename T>
void Angle<T>::operator-=(const Angle<T>& rhs){
_radians -= rhs._radians;
}
template <typename T>
void Angle<T>::operator*=(T multiplier){
_radians *= multiplier;
}
template <typename T>
void Angle<T>::operator/=(T divisor){
_radians /= divisor;
}
template <typename T>
bool Angle<T>::operator<(const Angle<T>& rhs) const{
return _radians < rhs._radians;
}
template <typename T>
bool Angle<T>::operator<=(const Angle<T>& rhs) const{
return _radians <= rhs._radians;
}
template <typename T>
bool Angle<T>::operator>(const Angle<T>& rhs) const{
return _radians > rhs._radians;
}
template <typename T>
bool Angle<T>::operator>=(const Angle<T>& rhs) const{
return _radians >= rhs._radians;
}
template <typename T>
bool Angle<T>::operator==(const Angle<T>& rhs) const{
return _radians == rhs._radians;
}
template <typename T>
bool Angle<T>::operator!=(const Angle<T>& rhs) const{
return _radians != rhs._radians;
}
//////////////////////////////////////////////////////////////////////////////////////////
// Chainable Relative Mutators //
//////////////////////////////////////////////////////////////////////////////////////////
template <typename T>
Angle<T>& Angle<T>::normalize() {
// this will cause _radians to be in value range ]-2pi, 2pi[
_radians = fmod(_radians, glm::two_pi<T>());
// ensure _radians are positive, ie in value range [0, 2pi[
if (_radians < T(0)) {
_radians += glm::two_pi<T>();
}
return *this;
}
template <typename T>
Angle<T>& Angle<T>::normalizeAround(const Angle<T>& center) {
_radians -= center._radians + glm::pi<T>();
normalize();
_radians += center._radians - glm::pi<T>();
return *this;
}
template <typename T>
Angle<T>& Angle<T>::clamp(const Angle<T>& min, const Angle<T>& max) {
const T& minRad = min._radians;
const T& maxRad = max._radians;
_radians = glm::clamp(_radians, minRad, maxRad);
return *this;
}
template <typename T>
Angle<T> Angle<T>::abs() const {
return Angle<T>::fromRadians(glm::abs(_radians));
}
} // namespace openspace::globebrowsing

View File

@@ -1,55 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___GEODETIC2___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___GEODETIC2___H__
#include <ghoul/glm.h>
namespace openspace::globebrowsing {
struct Geodetic2 {
Geodetic2(double latitude = 0.0, double longitude = 0.0);
Geodetic2(const Geodetic2& src) = default;
//static Geodetic2 fromCartesian(const Vec3& v);
//Vec3 asUnitCartesian() const;
glm::dvec2 toLonLatVec2() const;
bool operator==(const Geodetic2& other) const;
bool operator!=(const Geodetic2& other) const { return !(*this == (other)); }
Geodetic2 operator+(const Geodetic2& other) const;
Geodetic2 operator-(const Geodetic2& other) const;
Geodetic2 operator*(double scalar) const;
Geodetic2 operator/(double scalar) const;
double lat;
double lon;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___GEODETIC2___H__

View File

@@ -1,39 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___GEODETIC3___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___GEODETIC3___H__
#include <modules/globebrowsing/geometry/geodetic2.h>
namespace openspace::globebrowsing {
struct Geodetic3 {
Geodetic2 geodetic2;
double height;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___GEODETIC3___H__

View File

@@ -24,20 +24,12 @@
#include <modules/globebrowsing/globebrowsingmodule.h>
#include <modules/globebrowsing/cache/memoryawaretilecache.h>
#include <modules/globebrowsing/dashboard/dashboarditemglobelocation.h>
#include <modules/globebrowsing/geometry/geodetic3.h>
#include <modules/globebrowsing/geometry/geodeticpatch.h>
#include <modules/globebrowsing/tile/rawtiledatareader/gdalwrapper.h>
#include <modules/globebrowsing/tile/tileprovider/defaulttileprovider.h>
#include <modules/globebrowsing/tile/tileprovider/singleimageprovider.h>
#include <modules/globebrowsing/tile/tileprovider/sizereferencetileprovider.h>
#include <modules/globebrowsing/tile/tileprovider/temporaltileprovider.h>
#include <modules/globebrowsing/tile/tileprovider/texttileprovider.h>
#include <modules/globebrowsing/tile/tileprovider/tileindextileprovider.h>
#include <modules/globebrowsing/tile/tileprovider/tileprovider.h>
#include <modules/globebrowsing/tile/tileprovider/tileproviderbylevel.h>
#include <modules/globebrowsing/tile/tileprovider/tileproviderbyindex.h>
#include <modules/globebrowsing/src/basictypes.h>
#include <modules/globebrowsing/src/dashboarditemglobelocation.h>
#include <modules/globebrowsing/src/gdalwrapper.h>
#include <modules/globebrowsing/src/geodeticpatch.h>
#include <modules/globebrowsing/src/memoryawaretilecache.h>
#include <modules/globebrowsing/src/tileprovider.h>
#include <openspace/engine/globalscallbacks.h>
#include <openspace/scripting/lualibrary.h>
#include <openspace/util/factorymanager.h>
@@ -48,7 +40,6 @@
#include <ghoul/systemcapabilities/generalcapabilitiescomponent.h>
#include <vector>
#ifdef GLOBEBROWSING_USE_GDAL
#include <gdal.h>
#ifdef _MSC_VER
@@ -63,14 +54,11 @@
#pragma warning (pop)
#endif // _MSC_VER
#endif // GLOBEBROWSING_USE_GDAL
#include "globebrowsingmodule_lua.inl"
namespace {
constexpr const char* _loggerCat = "GlobeBrowsingModule";
#ifdef GLOBEBROWSING_USE_GDAL
openspace::GlobeBrowsingModule::Capabilities
parseSubDatasets(char** subDatasets, int nSubdatasets)
{
@@ -121,9 +109,6 @@ namespace {
return result;
}
#endif // GLOBEBROWSING_USE_GDAL
} // namespace
namespace openspace {
@@ -138,14 +123,18 @@ void GlobeBrowsingModule::internalInitialize(const ghoul::Dictionary&) {
_tileCache = std::make_unique<globebrowsing::cache::MemoryAwareTileCache>();
addPropertySubOwner(*_tileCache);
#ifdef GLOBEBROWSING_USE_GDAL
tileprovider::initializeDefaultTile();
// Convert from MB to Bytes
GdalWrapper::create(
16ULL * 1024ULL * 1024ULL, // 16 MB
static_cast<size_t>(CpuCap.installedMainMemory() * 0.25 * 1024 * 1024)
);
addPropertySubOwner(GdalWrapper::ref());
#endif // GLOBEBROWSING_USE_GDAL
});
global::callback::deinitializeGL.push_back([]() {
tileprovider::deinitializeDefaultTile();
});
@@ -153,9 +142,7 @@ void GlobeBrowsingModule::internalInitialize(const ghoul::Dictionary&) {
global::callback::render.push_back([&]() { _tileCache->update(); });
// Deinitialize
#ifdef GLOBEBROWSING_USE_GDAL
global::callback::deinitialize.push_back([&]() { GdalWrapper::ref().destroy(); });
#endif // GLOBEBROWSING_USE_GDAL
// Get factories
auto fRenderable = FactoryManager::ref().factory<Renderable>();
@@ -177,12 +164,10 @@ void GlobeBrowsingModule::internalInitialize(const ghoul::Dictionary&) {
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(
layergroupid::TypeID::SingleImageTileLayer
)]);
#ifdef GLOBEBROWSING_USE_GDAL
fTileProvider->registerClass<tileprovider::TemporalTileProvider>(
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(
layergroupid::TypeID::TemporalTileLayer
)]);
#endif // GLOBEBROWSING_USE_GDAL
fTileProvider->registerClass<tileprovider::TileIndexTileProvider>(
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(
layergroupid::TypeID::TileIndexTileLayer
@@ -273,7 +258,6 @@ scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const {
"Get geographic coordinates of the camera poosition in latitude, "
"longitude, and altitude"
},
#ifdef GLOBEBROWSING_USE_GDAL
{
"loadWMSCapabilities",
&globebrowsing::luascriptfunctions::loadWMSCapabilities,
@@ -304,7 +288,6 @@ scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const {
"component of the returned table can be used in the 'FilePath' argument "
"for a call to the 'addLayer' function to add the value to a globe."
}
#endif // GLOBEBROWSING_USE_GDAL
};
res.scripts = {
absPath("${MODULE_GLOBEBROWSING}/scripts/layer_support.lua")
@@ -321,9 +304,11 @@ void GlobeBrowsingModule::goToChunk(int x, int y, int level) {
void GlobeBrowsingModule::goToGeo(double latitude, double longitude) {
using namespace globebrowsing;
Camera* cam = global::navigationHandler.camera();
goToGeodetic2(*cam, Geodetic2(
Angle<double>::fromDegrees(latitude).asRadians(),
Angle<double>::fromDegrees(longitude).asRadians()), true);
goToGeodetic2(
*cam,
Geodetic2{ glm::radians(latitude), glm::radians(longitude) },
true
);
}
void GlobeBrowsingModule::goToGeo(double latitude, double longitude,
@@ -335,9 +320,7 @@ void GlobeBrowsingModule::goToGeo(double latitude, double longitude,
goToGeodetic3(
*cam,
{
Geodetic2(
Angle<double>::fromDegrees(latitude).asRadians(),
Angle<double>::fromDegrees(longitude).asRadians()),
Geodetic2{ glm::radians(latitude), glm::radians(longitude) },
altitude
},
true
@@ -351,10 +334,7 @@ glm::vec3 GlobeBrowsingModule::cartesianCoordinatesFromGeo(
using namespace globebrowsing;
const Geodetic3 pos = {
{
Angle<double>::fromDegrees(latitude).asRadians(),
Angle<double>::fromDegrees(longitude).asRadians()
},
{ glm::radians(latitude), glm::radians(longitude) },
altitude
};
@@ -379,7 +359,7 @@ void GlobeBrowsingModule::goToChunk(Camera& camera, const globebrowsing::TileInd
// Camera position in model space
const glm::dvec3 camPos = camera.positionVec3();
const glm::dmat4 inverseModelTransform = globe->inverseModelTransform();
const glm::dmat4 inverseModelTransform = glm::inverse(globe->modelTransform());
const glm::dvec3 cameraPositionModelSpace = glm::dvec3(
inverseModelTransform * glm::dvec4(camPos, 1)
);
@@ -389,7 +369,10 @@ void GlobeBrowsingModule::goToChunk(Camera& camera, const globebrowsing::TileInd
Geodetic2 positionOnPatch = patch.size();
positionOnPatch.lat *= uv.y;
positionOnPatch.lon *= uv.x;
const Geodetic2 pointPosition = corner + positionOnPatch;
const Geodetic2 pointPosition = {
corner.lat + positionOnPatch.lat,
corner.lon + positionOnPatch.lon
};
const glm::dvec3 positionOnEllipsoid = globe->ellipsoid().geodeticSurfaceProjection(
cameraPositionModelSpace
@@ -467,7 +450,7 @@ void GlobeBrowsingModule::resetCameraDirection(Camera& camera,
geo2
);
const glm::dvec3 slightlyNorth = globe->ellipsoid().cartesianSurfacePosition(
Geodetic2(geo2.lat + 0.001, geo2.lon)
Geodetic2{ geo2.lat + 0.001, geo2.lon }
);
const glm::dvec3 lookUpModelSpace = glm::normalize(
slightlyNorth - positionModelSpace
@@ -534,8 +517,6 @@ std::string GlobeBrowsingModule::layerTypeNamesList() {
return listLayerTypes;
}
#ifdef GLOBEBROWSING_USE_GDAL
void GlobeBrowsingModule::loadWMSCapabilities(std::string name, std::string globe,
std::string url)
{
@@ -624,6 +605,4 @@ bool GlobeBrowsingModule::hasUrlInfo(const std::string& globe) const {
return _urlList.find(globe) != _urlList.end();
}
#endif // GLOBEBROWSING_USE_GDAL
} // namespace openspace

View File

@@ -61,7 +61,6 @@ public:
scripting::LuaLibrary luaLibrary() const override;
const globebrowsing::RenderableGlobe* castFocusNodeRenderableToGlobe();
#ifdef GLOBEBROWSING_USE_GDAL
struct Layer {
std::string name;
std::string url;
@@ -82,7 +81,6 @@ public:
bool hasUrlInfo(const std::string& globe) const;
void removeWMSServer(const std::string& name);
#endif // GLOBEBROWSING_USE_GDAL
protected:
void internalInitialize(const ghoul::Dictionary&) override;
@@ -108,14 +106,12 @@ private:
std::unique_ptr<globebrowsing::cache::MemoryAwareTileCache> _tileCache;
#ifdef GLOBEBROWSING_USE_GDAL
// name -> capabilities
std::map<std::string, std::future<Capabilities>> _inFlightCapabilitiesMap;
// name -> capabilities
std::map<std::string, Capabilities> _capabilitiesMap;
std::multimap<std::string, UrlInfo> _urlList;
#endif // GLOBEBROWSING_USE_GDAL
};
} // namespace openspace

View File

@@ -22,17 +22,15 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/globebrowsing/globes/renderableglobe.h>
#include <modules/globebrowsing/src/renderableglobe.h>
#include <modules/globebrowsing/geometry/angle.h>
#include <modules/globebrowsing/rendering/layer/layermanager.h>
#include <modules/globebrowsing/rendering/layer/layer.h>
#include <openspace/interaction/navigationhandler.h>
#include <modules/globebrowsing/src/layer.h>
#include <modules/globebrowsing/src/layermanager.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/interaction/navigationhandler.h>
#include <openspace/rendering/renderable.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/scene.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/query/query.h>
@@ -58,13 +56,15 @@ int addLayer(lua_State* L) {
}
// Get the renderable globe
const RenderableGlobe* globe = dynamic_cast<const RenderableGlobe*>(n->renderable());
RenderableGlobe* globe = dynamic_cast<RenderableGlobe*>(n->renderable());
if (!globe) {
return ghoul::lua::luaError(L, "Renderable is not a globe: " + globeName);
}
// Get the layer group
layergroupid::GroupID groupID = layergroupid::getGroupIDFromName(layerGroupName);
layergroupid::GroupID groupID = ghoul::from_string<layergroupid::GroupID>(
layerGroupName
);
if (groupID == layergroupid::GroupID::Unknown) {
return ghoul::lua::luaError(L, "Unknown layer group: " + layerGroupName);
}
@@ -81,7 +81,7 @@ int addLayer(lua_State* L) {
}
lua_settop(L, 0);
std::shared_ptr<Layer> layer = globe->layerManager()->addLayer(groupID, d);
Layer* layer = globe->layerManager().addLayer(groupID, d);
if (layer) {
layer->initialize();
}
@@ -108,18 +108,20 @@ int deleteLayer(lua_State* L) {
}
// Get the renderable globe
const RenderableGlobe* globe = dynamic_cast<const RenderableGlobe*>(n->renderable());
RenderableGlobe* globe = dynamic_cast<RenderableGlobe*>(n->renderable());
if (!globe) {
return ghoul::lua::luaError(L, "Renderable is not a globe: " + globeName);
}
// Get the layer group
layergroupid::GroupID groupID = layergroupid::getGroupIDFromName(layerGroupName);
layergroupid::GroupID groupID = ghoul::from_string<layergroupid::GroupID>(
layerGroupName
);
if (groupID == layergroupid::GroupID::Unknown) {
return ghoul::lua::luaError(L, "Unknown layer group: " + layerGroupName);
}
globe->layerManager()->deleteLayer(groupID, layerName);
globe->layerManager().deleteLayer(groupID, layerName);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
@@ -219,18 +221,12 @@ int getGeoPositionForCamera(lua_State* L) {
const double altitude = glm::length(cameraPositionModelSpace -
posHandle.centerToReferenceSurface);
ghoul::lua::push(
L,
Angle<double>::fromRadians(geo2.lat).asDegrees(),
Angle<double>::fromRadians(geo2.lon).asDegrees(),
altitude
);
ghoul::lua::push(L, glm::degrees(geo2.lat), glm::degrees(geo2.lon), altitude);
ghoul_assert(lua_gettop(L) == 3, "Incorrect number of items left on stack");
return 3;
}
#ifdef GLOBEBROWSING_USE_GDAL
int loadWMSCapabilities(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::loadWMSCapabilities");
@@ -294,6 +290,5 @@ int capabilities(lua_State* L) {
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
return 1;
}
#endif // GLOBEBROWSING_USE_GDAL
} // namespace openspace::globebrowsing::luascriptfunctions

View File

@@ -1,397 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/globes/chunkedlodglobe.h>
#include <modules/globebrowsing/chunk/chunk.h>
#include <modules/globebrowsing/chunk/chunklevelevaluator/chunklevelevaluator.h>
#include <modules/globebrowsing/chunk/chunklevelevaluator/availabletiledataevaluator.h>
#include <modules/globebrowsing/chunk/chunklevelevaluator/distanceevaluator.h>
#include <modules/globebrowsing/chunk/chunklevelevaluator/projectedareaevaluator.h>
#include <modules/globebrowsing/chunk/chunknode.h>
#include <modules/globebrowsing/chunk/culling/chunkculler.h>
#include <modules/globebrowsing/chunk/culling/frustumculler.h>
#include <modules/globebrowsing/chunk/culling/horizonculler.h>
#include <modules/globebrowsing/globes/renderableglobe.h>
#include <modules/globebrowsing/meshes/skirtedgrid.h>
#include <modules/globebrowsing/tile/tileindex.h>
#include <modules/globebrowsing/tile/tileprovider/tileprovider.h>
#include <modules/globebrowsing/rendering/chunkrenderer.h>
#include <modules/globebrowsing/rendering/layer/layer.h>
#include <modules/globebrowsing/rendering/layer/layergroup.h>
#include <modules/globebrowsing/rendering/layer/layermanager.h>
#include <modules/debugging/rendering/debugrenderer.h>
#include <openspace/util/time.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/opengl/texture.h>
//#include <math.h>
namespace {
const openspace::globebrowsing::GeodeticPatch Coverage =
openspace::globebrowsing::GeodeticPatch(0, 0, 90, 180);
const openspace::globebrowsing::TileIndex LeftHemisphereIndex =
openspace::globebrowsing::TileIndex(0, 0, 1);
const openspace::globebrowsing::TileIndex RightHemisphereIndex =
openspace::globebrowsing::TileIndex(1, 0, 1);
} // namespace
namespace openspace::globebrowsing {
ChunkedLodGlobe::ChunkedLodGlobe(const RenderableGlobe& owner, size_t segmentsPerPatch,
std::shared_ptr<LayerManager> layerManager,
Ellipsoid& ellipsoid)
: Renderable({ { "Identifier", owner.identifier() }, { "Name", owner.guiName() } })
#ifdef DEBUG_GLOBEBROWSING_STATSRECORD
, stats(StatsCollector(absPath("test_stats"), 1, StatsCollector::Enabled::No))
#endif // DEBUG_GLOBEBROWSING_STATSRECORD
, _owner(owner)
, _leftRoot(std::make_unique<ChunkNode>(Chunk(owner, LeftHemisphereIndex)))
, _rightRoot(std::make_unique<ChunkNode>(Chunk(owner, RightHemisphereIndex)))
, _layerManager(layerManager)
{
std::shared_ptr<SkirtedGrid> geometry = std::make_shared<SkirtedGrid>(
static_cast<unsigned int>(segmentsPerPatch),
static_cast<unsigned int>(segmentsPerPatch),
TriangleSoup::Positions::No,
TriangleSoup::TextureCoordinates::Yes,
TriangleSoup::Normals::No
);
_chunkCullers.push_back(std::make_unique<culling::HorizonCuller>());
_chunkCullers.push_back(std::make_unique<culling::FrustumCuller>(
AABB3(
glm::vec3(-1, -1, 0),
glm::vec3(1, 1, 1e35)
)
));
_chunkEvaluatorByAvailableTiles =
std::make_unique<chunklevelevaluator::AvailableTileData>();
_chunkEvaluatorByProjectedArea =
std::make_unique<chunklevelevaluator::ProjectedArea>();
_chunkEvaluatorByDistance = std::make_unique<chunklevelevaluator::Distance>();
_renderer = std::make_unique<ChunkRenderer>(geometry, layerManager, ellipsoid);
}
ChunkedLodGlobe::~ChunkedLodGlobe() {} // NOLINT
bool ChunkedLodGlobe::isReady() const {
return true;
}
std::shared_ptr<LayerManager> ChunkedLodGlobe::layerManager() const {
return _layerManager;
}
bool ChunkedLodGlobe::testIfCullable(const Chunk& chunk,
const RenderData& renderData) const
{
if (_owner.debugProperties().performHorizonCulling &&
_chunkCullers[0]->isCullable(chunk, renderData)) {
return true;
}
if (_owner.debugProperties().performFrustumCulling &&
_chunkCullers[1]->isCullable(chunk, renderData)) {
return true;
}
return false;
}
const ChunkNode& ChunkedLodGlobe::findChunkNode(const Geodetic2& location) const {
ghoul_assert(
Coverage.contains(location),
"Point must be in lat [-90, 90] and lon [-180, 180]"
);
return location.lon < Coverage.center().lon ?
_leftRoot->find(location) :
_rightRoot->find(location);
}
int ChunkedLodGlobe::desiredLevel(const Chunk& chunk,
const RenderData& renderData) const
{
int desiredLevel = 0;
if (_owner.debugProperties().levelByProjectedAreaElseDistance) {
desiredLevel = _chunkEvaluatorByProjectedArea->desiredLevel(chunk, renderData);
}
else {
desiredLevel = _chunkEvaluatorByDistance->desiredLevel(chunk, renderData);
}
int levelByAvailableData = _chunkEvaluatorByAvailableTiles->desiredLevel(
chunk,
renderData
);
if (levelByAvailableData != chunklevelevaluator::Evaluator::UnknownDesiredLevel &&
_owner.debugProperties().limitLevelByAvailableData)
{
desiredLevel = glm::min(desiredLevel, levelByAvailableData);
}
desiredLevel = glm::clamp(desiredLevel, MinSplitDepth, MaxSplitDepth);
return desiredLevel;
}
float ChunkedLodGlobe::getHeight(const glm::dvec3& position) const {
float height = 0;
// Get the uv coordinates to sample from
const Geodetic2 geodeticPosition = _owner.ellipsoid().cartesianToGeodetic2(position);
const int chunkLevel = findChunkNode(geodeticPosition).chunk().tileIndex().level;
const TileIndex tileIndex = TileIndex(geodeticPosition, chunkLevel);
const GeodeticPatch patch = GeodeticPatch(tileIndex);
const Geodetic2 geoDiffPatch = patch.corner(Quad::NORTH_EAST) -
patch.corner(Quad::SOUTH_WEST);
const Geodetic2 geoDiffPoint = geodeticPosition - patch.corner(Quad::SOUTH_WEST);
const glm::vec2 patchUV = glm::vec2(
geoDiffPoint.lon / geoDiffPatch.lon,
geoDiffPoint.lat / geoDiffPatch.lat
);
// Get the tile providers for the height maps
const std::vector<std::shared_ptr<Layer>>& heightMapLayers =
_layerManager->layerGroup(layergroupid::GroupID::HeightLayers).activeLayers();
for (const std::shared_ptr<Layer>& layer : heightMapLayers) {
tileprovider::TileProvider* tileProvider = layer->tileProvider();
if (!tileProvider) {
continue;
}
// Transform the uv coordinates to the current tile texture
const ChunkTile chunkTile = tileProvider->chunkTile(tileIndex);
const Tile& tile = chunkTile.tile;
const TileUvTransform& uvTransform = chunkTile.uvTransform;
const TileDepthTransform& depthTransform = tileProvider->depthTransform();
if (tile.status() != Tile::Status::OK) {
return 0;
}
ghoul::opengl::Texture* tileTexture = tile.texture();
if (!tileTexture) {
return 0;
}
glm::vec2 transformedUv = layer->TileUvToTextureSamplePosition(
uvTransform,
patchUV,
glm::uvec2(tileTexture->dimensions())
);
// Sample and do linear interpolation
// (could possibly be moved as a function in ghoul texture)
// Suggestion: a function in ghoul::opengl::Texture that takes uv coordinates
// in range [0,1] and uses the set interpolation method and clamping.
const glm::uvec3 dimensions = tileTexture->dimensions();
const glm::vec2 samplePos = transformedUv * glm::vec2(dimensions);
glm::uvec2 samplePos00 = samplePos;
samplePos00 = glm::clamp(
samplePos00,
glm::uvec2(0, 0),
glm::uvec2(dimensions) - glm::uvec2(1)
);
const glm::vec2 samplePosFract = samplePos - glm::vec2(samplePos00);
const glm::uvec2 samplePos10 = glm::min(
samplePos00 + glm::uvec2(1, 0),
glm::uvec2(dimensions) - glm::uvec2(1)
);
const glm::uvec2 samplePos01 = glm::min(
samplePos00 + glm::uvec2(0, 1),
glm::uvec2(dimensions) - glm::uvec2(1)
);
const glm::uvec2 samplePos11 = glm::min(
samplePos00 + glm::uvec2(1, 1),
glm::uvec2(dimensions) - glm::uvec2(1)
);
const float sample00 = tileTexture->texelAsFloat(samplePos00).x;
const float sample10 = tileTexture->texelAsFloat(samplePos10).x;
const float sample01 = tileTexture->texelAsFloat(samplePos01).x;
const float sample11 = tileTexture->texelAsFloat(samplePos11).x;
// In case the texture has NaN or no data values don't use this height map.
const bool anySampleIsNaN =
std::isnan(sample00) ||
std::isnan(sample01) ||
std::isnan(sample10) ||
std::isnan(sample11);
const bool anySampleIsNoData =
sample00 == tileProvider->noDataValueAsFloat() ||
sample01 == tileProvider->noDataValueAsFloat() ||
sample10 == tileProvider->noDataValueAsFloat() ||
sample11 == tileProvider->noDataValueAsFloat();
if (anySampleIsNaN || anySampleIsNoData) {
continue;
}
const float sample0 = sample00 * (1.f - samplePosFract.x) +
sample10 * samplePosFract.x;
const float sample1 = sample01 * (1.f - samplePosFract.x) +
sample11 * samplePosFract.x;
const float sample = sample0 * (1.f - samplePosFract.y) +
sample1 * samplePosFract.y;
// Same as is used in the shader. This is not a perfect solution but
// if the sample is actually a no-data-value (min_float) the interpolated
// value might not be. Therefore we have a cut-off. Assuming no data value
// is smaller than -100000
if (sample > -100000) {
// Perform depth transform to get the value in meters
height = depthTransform.depthOffset + depthTransform.depthScale * sample;
// Make sure that the height value follows the layer settings.
// For example if the multiplier is set to a value bigger than one,
// the sampled height should be modified as well.
height = layer->renderSettings().performLayerSettings(height);
}
}
// Return the result
return height;
}
void ChunkedLodGlobe::notifyShaderRecompilation() {
_shadersNeedRecompilation = true;
}
void ChunkedLodGlobe::recompileShaders() {
_renderer->recompileShaders(_owner);
_shadersNeedRecompilation = false;
}
void ChunkedLodGlobe::render(const RenderData& data, RendererTasks&) {
#ifdef DEBUG_GLOBEBROWSING_STATSRECORD
stats.startNewRecord();
#endif // DEBUG_GLOBEBROWSING_STATSRECORD
if (_shadersNeedRecompilation) {
_renderer->recompileShaders(_owner);
_shadersNeedRecompilation = false;
}
#ifdef DEBUG_GLOBEBROWSING_STATSRECORD
auto duration = std::chrono::system_clock::now().time_since_epoch();
auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
stats.i["time"] = millis;
#endif // DEBUG_GLOBEBROWSING_STATSRECORD
_leftRoot->updateChunkTree(data);
_rightRoot->updateChunkTree(data);
// Calculate the MVP matrix
const glm::dmat4 viewTransform = glm::dmat4(data.camera.combinedViewMatrix());
const glm::dmat4 vp = glm::dmat4(data.camera.sgctInternal.projectionMatrix()) *
viewTransform;
const glm::dmat4 mvp = vp * _owner.modelTransform();
// Render function
auto renderJob = [this, &data, &mvp](const ChunkNode& chunkNode) {
#ifdef DEBUG_GLOBEBROWSING_STATSRECORD
stats.i["chunks nodes"]++;
#endif // DEBUG_GLOBEBROWSING_STATSRECORD
const Chunk& chunk = chunkNode.chunk();
if (chunkNode.isLeaf()) {
#ifdef DEBUG_GLOBEBROWSING_STATSRECORD
stats.i["leafs chunk nodes"]++;
#endif // DEBUG_GLOBEBROWSING_STATSRECORD
if (chunk.isVisible()) {
#ifdef DEBUG_GLOBEBROWSING_STATSRECORD
stats.i["rendered chunks"]++;
#endif // DEBUG_GLOBEBROWSING_STATSRECORD
_renderer->renderChunk(chunkNode.chunk(), data);
debugRenderChunk(chunk, mvp);
}
}
};
_leftRoot->breadthFirst(renderJob);
_rightRoot->breadthFirst(renderJob);
//_leftRoot->reverseBreadthFirst(renderJob);
//_rightRoot->reverseBreadthFirst(renderJob);
#ifdef DEBUG_GLOBEBROWSING_STATSRECORD
auto duration2 = std::chrono::system_clock::now().time_since_epoch();
auto ms2 = std::chrono::duration_cast<std::chrono::milliseconds>(duration2).count();
stats.i["chunk globe render time"] = ms2 - millis;
#endif // DEBUG_GLOBEBROWSING_STATSRECORD
}
void ChunkedLodGlobe::debugRenderChunk(const Chunk& chunk, const glm::dmat4& mvp) const {
if (_owner.debugProperties().showChunkBounds ||
_owner.debugProperties().showChunkAABB)
{
const std::vector<glm::dvec4>& modelSpaceCorners =
chunk.boundingPolyhedronCorners();
std::vector<glm::vec4> clippingSpaceCorners(8);
AABB3 screenSpaceBounds;
for (size_t i = 0; i < 8; ++i) {
const glm::vec4& clippingSpaceCorner = mvp * modelSpaceCorners[i];
clippingSpaceCorners[i] = clippingSpaceCorner;
glm::vec3 screenSpaceCorner =
glm::vec3((1.f / clippingSpaceCorner.w) * clippingSpaceCorner);
screenSpaceBounds.expand(std::move(screenSpaceCorner));
}
const unsigned int colorBits = 1 + chunk.tileIndex().level % 6;
const glm::vec4 color = glm::vec4(
colorBits & 1,
colorBits & 2,
colorBits & 4,
0.3f
);
if (_owner.debugProperties().showChunkBounds) {
DebugRenderer::ref().renderNiceBox(clippingSpaceCorners, color);
}
if (_owner.debugProperties().showChunkAABB) {
const std::vector<glm::vec4>& screenSpacePoints =
DebugRenderer::ref().verticesFor(screenSpaceBounds);
DebugRenderer::ref().renderNiceBox(screenSpacePoints, color);
}
}
}
void ChunkedLodGlobe::update(const UpdateData& data) {
setBoundingSphere(static_cast<float>(
_owner.ellipsoid().maximumRadius() * data.modelTransform.scale
));
_renderer->update();
}
} // namespace openspace::globebrowsing

View File

@@ -1,154 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___CHUNKED_LOD_GLOBE___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___CHUNKED_LOD_GLOBE___H__
#include <openspace/rendering/renderable.h>
#include <memory>
//#define DEBUG_GLOBEBROWSING_STATSRECORD
#ifdef DEBUG_GLOBEBROWSING_STATSRECORD
#include <modules/globebrowsing/other/statscollector.h>
#endif // DEBUG_GLOBEBROWSING_STATSRECORD
namespace openspace::globebrowsing {
namespace chunklevelevaluator { class Evaluator; }
namespace culling { class ChunkCuller; }
class Chunk;
class ChunkNode;
class ChunkRenderer;
class Ellipsoid;
struct Geodetic2;
class LayerManager;
class RenderableGlobe;
class ChunkedLodGlobe : public Renderable {
public:
ChunkedLodGlobe(const RenderableGlobe& owner, size_t segmentsPerPatch,
std::shared_ptr<LayerManager> layerManager, Ellipsoid& ellipsoid);
~ChunkedLodGlobe();
bool isReady() const override;
void render(const RenderData& data, RendererTasks& rendererTask) override;
void update(const UpdateData& data) override;
/**
* Traverse the chunk tree and find the highest level chunk node.
*
* \param location is given in geodetic coordinates and must be in the range
* latitude [-90, 90] and longitude [-180, 180]. In other words, it must be a
* position defined on the globe in georeferenced coordinates.
*/
const ChunkNode& findChunkNode(const Geodetic2& location) const;
/**
* Test if a specific chunk can saf;ely be culled without affecting the rendered
* image.
*
* Goes through all available <code>ChunkCuller</code>s and check if any of them
* allows culling of the <code>Chunk</code>s in question.
*/
bool testIfCullable(const Chunk& chunk, const RenderData& renderData) const;
/**
* Gets the desired level which can be used to determine if a chunk should split
* or merge.
*
* Using <code>ChunkLevelEvaluator</code>s, the desired level can be higher or
* lower than the current level of the <code>Chunks</code>s
* <code>TileIndex</code>. If the desired level is higher than that of the
* <code>Chunk</code>, it wants to split. If it is lower, it wants to merge with
* its siblings.
*/
int desiredLevel(const Chunk& chunk, const RenderData& renderData) const;
/**
* Calculates the height from the surface of the reference ellipsoid to the
* heigh mapped surface.
*
* The height can be negative if the height map contains negative values.
*
* \param <code>position</code> is the position of a point that gets geodetically
* projected on the reference ellipsoid. <code>position</code> must be in
* cartesian model space.
* \returns the height from the reference ellipsoid to the globe surface.
*/
float getHeight(const glm::dvec3& position) const;
/**
* Notifies the renderer to recompile its shaders the next time the render function is
* called. The actual shader recompilation takes place in the render function because
* properties that the shader depends on need to be properly synced.
*/
void notifyShaderRecompilation();
/**
* Directly recompile the shaders of the renderer.
*/
void recompileShaders();
constexpr static const int MinSplitDepth = 2;
constexpr static const int MaxSplitDepth = 22;
std::shared_ptr<LayerManager> layerManager() const;
#ifdef DEBUG_GLOBEBROWSING_STATSRECORD
StatsCollector stats;
#endif // DEBUG_GLOBEBROWSING_STATSRECORD
private:
void debugRenderChunk(const Chunk& chunk, const glm::dmat4& mvp) const;
const RenderableGlobe& _owner;
// Covers all negative longitudes
std::unique_ptr<ChunkNode> _leftRoot;
// Covers all positive longitudes
std::unique_ptr<ChunkNode> _rightRoot;
// the patch used for actual rendering
std::unique_ptr<ChunkRenderer> _renderer;
std::vector<std::unique_ptr<culling::ChunkCuller>> _chunkCullers;
std::unique_ptr<chunklevelevaluator::Evaluator> _chunkEvaluatorByAvailableTiles;
std::unique_ptr<chunklevelevaluator::Evaluator> _chunkEvaluatorByProjectedArea;
std::unique_ptr<chunklevelevaluator::Evaluator> _chunkEvaluatorByDistance;
std::shared_ptr<LayerManager> _layerManager;
bool _shadersNeedRecompilation = true;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___CHUNKED_LOD_GLOBE___H__

View File

@@ -1,187 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/globes/pointglobe.h>
#include <modules/globebrowsing/globes/renderableglobe.h>
#include <openspace/engine/globals.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/util/updatestructures.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/opengl/programobject.h>
namespace {
constexpr const std::array<const char*, 3> UniformNames = {
"lightIntensityClamped", "modelViewTransform", "projectionTransform"
};
constexpr openspace::properties::Property::PropertyInfo IntensityClampInfo = {
"IntensityClamp",
"Intensity clamp",
""
};
constexpr openspace::properties::Property::PropertyInfo LightIntensityInfo = {
"LightIntensity",
"Light intensity",
"" // @TODO Missing documentation
};
} // namespace
namespace openspace::globebrowsing {
PointGlobe::PointGlobe(const RenderableGlobe& owner)
: Renderable({ { "Identifier", owner.identifier() }, { "Name", owner.guiName() } })
, _owner(owner)
, _intensityClamp(IntensityClampInfo, 1.f, 0.f, 1.f)
, _lightIntensity(LightIntensityInfo, 1.f, 0.f, 50.f)
{
addProperty(_intensityClamp);
addProperty(_lightIntensity);
}
PointGlobe::~PointGlobe() {
glDeleteBuffers(1, &_vertexBufferID);
glDeleteVertexArrays(1, &_vaoID);
}
void PointGlobe::initialize() {
_programObject = global::renderEngine.buildRenderProgram(
"PointGlobe",
absPath("${MODULE_GLOBEBROWSING}/shaders/pointglobe_vs.glsl"),
absPath("${MODULE_GLOBEBROWSING}/shaders/pointglobe_fs.glsl")
);
ghoul::opengl::updateUniformLocations(*_programObject, _uniformCache, UniformNames);
glGenVertexArrays(1, &_vaoID);
glGenBuffers(1, &_vertexBufferID);
glBindVertexArray(_vaoID);
std::array<float, 2 * 6> quadVertexData = {
-1.f, -1.f,
1.f, -1.f,
-1.f, 1.f,
-1.f, 1.f,
1.f, -1.f,
1.f, 1.f
};
// Vertex buffer
glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferID);
glBufferData(
GL_ARRAY_BUFFER,
sizeof(float) * quadVertexData.size(),
quadVertexData.data(),
GL_STATIC_DRAW
);
// Position at location 0
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), nullptr);
glBindVertexArray(0);
}
void PointGlobe::deinitialize() {
glDeleteVertexArrays(1, &_vaoID);
glDeleteBuffers(1, &_vertexBufferID);
}
bool PointGlobe::isReady() const {
return (_vaoID != 0) && (_vertexBufferID != 0);
}
void PointGlobe::render(const RenderData& data, RendererTasks&) {
_programObject->activate();
// Calculate variables to be used as uniform variables in shader
const glm::dvec3 bodyPosition = data.modelTransform.translation;
const glm::dmat4 rotationTransform = glm::lookAt(
glm::dvec3(0.0f),
data.camera.positionVec3() - bodyPosition,
glm::normalize(glm::dvec3(1000000.0f) - bodyPosition)
);
const glm::dvec3 camToBody = bodyPosition - data.camera.positionVec3();
const float distanceToBody = static_cast<float>(glm::length(camToBody));
const float avgRadius = static_cast<float>(_owner.ellipsoid().averageRadius());
const float lightIntensity = static_cast<float>(
_lightIntensity.value() * data.modelTransform.scale * avgRadius / distanceToBody
);
const float lightIntensityClamped = glm::min(lightIntensity, _intensityClamp.value());
//float lightOverflow = glm::max(lightIntensity - lightIntensityClamped, 0.0f);
const float billboardRadius = lightIntensityClamped * distanceToBody;
const glm::dmat4 scaleTransform = glm::scale(
glm::dmat4(1.0), glm::dvec3(billboardRadius)
);
setBoundingSphere(billboardRadius);
// Model transform and view transform needs to be in double precision
const glm::dmat4 modelTransform = glm::translate(glm::dmat4(1.0), bodyPosition) *
glm::inverse(rotationTransform) *
scaleTransform; // Scale
const glm::dmat4 modelViewTransform = data.camera.combinedViewMatrix() *
modelTransform;
_programObject->setUniform(
_uniformCache.lightIntensityClamped,
lightIntensityClamped
);
//_program->setUniform("lightOverflow", lightOverflow);
//_program->setUniform("directionToSunViewSpace", directionToSunViewSpace);
_programObject->setUniform(
_uniformCache.modelView,
glm::mat4(modelViewTransform)
);
_programObject->setUniform(
_uniformCache.projection,
data.camera.sgctInternal.projectionMatrix()
);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glBindVertexArray(_vaoID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vertexBufferID);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
_programObject->deactivate();
}
} // namespace openspace::globebrowsing

View File

@@ -1,65 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___POINTGLOBE___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___POINTGLOBE___H__
#include <openspace/rendering/renderable.h>
#include <openspace/properties/scalar/floatproperty.h>
#include <ghoul/opengl/ghoul_gl.h>
#include <ghoul/opengl/uniformcache.h>
namespace ghoul::opengl { class ProgramObject; }
namespace openspace::globebrowsing {
class RenderableGlobe;
class PointGlobe : public Renderable {
public:
PointGlobe(const RenderableGlobe& owner);
virtual ~PointGlobe();
void initialize() override;
void deinitialize() override;
bool isReady() const override;
void render(const RenderData& data, RendererTasks& rendererTask) override;
private:
const RenderableGlobe& _owner;
std::unique_ptr<ghoul::opengl::ProgramObject> _programObject;
UniformCache(lightIntensityClamped, modelView, projection) _uniformCache;
GLuint _vertexBufferID = 0;
GLuint _vaoID = 0;
properties::FloatProperty _intensityClamp;
properties::FloatProperty _lightIntensity;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___POINTGLOBE___H__

View File

@@ -1,534 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/globes/renderableglobe.h>
#include <modules/debugging/rendering/debugrenderer.h>
#include <modules/globebrowsing/globes/chunkedlodglobe.h>
#include <modules/globebrowsing/globes/pointglobe.h>
#include <modules/globebrowsing/rendering/layer/layermanager.h>
#include <ghoul/logging/logmanager.h>
namespace {
constexpr const char* keyFrame = "Frame";
constexpr const char* keyRadii = "Radii";
constexpr const char* keySegmentsPerPatch = "SegmentsPerPatch";
constexpr const char* keyLayers = "Layers";
constexpr const char* keyShadowGroup = "ShadowGroup";
constexpr const char* keyShadowSource = "Source";
constexpr const char* keyShadowCaster = "Caster";
constexpr openspace::properties::Property::PropertyInfo SaveOrThrowInfo = {
"SaveOrThrowCamera",
"Save or throw camera",
"" // @TODO Missing documentation
};
constexpr openspace::properties::Property::PropertyInfo ShowChunkEdgeInfo = {
"ShowChunkEdges",
"Show chunk edges",
"" // @TODO Missing documentation
};
constexpr openspace::properties::Property::PropertyInfo ShowChunkBoundsInfo = {
"ShowChunkBounds",
"Show chunk bounds",
"" // @TODO Missing documentation
};
constexpr openspace::properties::Property::PropertyInfo ShowChunkAABBInfo = {
"ShowChunkAABB",
"Show chunk AABB",
"" // @TODO Missing documentation
};
constexpr openspace::properties::Property::PropertyInfo HeightResolutionInfo = {
"ShowHeightResolution",
"Show height resolution",
"" // @TODO Missing documentation
};
constexpr openspace::properties::Property::PropertyInfo HeightIntensityInfo = {
"ShowHeightIntensities",
"Show height intensities",
"" // @TODO Missing documentation
};
constexpr openspace::properties::Property::PropertyInfo FrustumCullingInfo = {
"PerformFrustumCulling",
"Perform frustum culling",
"" // @TODO Missing documentation
};
constexpr openspace::properties::Property::PropertyInfo HorizonCullingInfo = {
"PerformHorizonCulling",
"Perform horizon culling",
"" // @TODO Missing documentation
};
constexpr openspace::properties::Property::PropertyInfo LevelProjectedAreaInfo = {
"LevelByProjectedAreaElseDistance",
"Level by projected area (else distance)",
"" // @TODO Missing documentation
};
constexpr openspace::properties::Property::PropertyInfo ResetTileProviderInfo = {
"ResetTileProviders",
"Reset tile providers",
"" // @TODO Missing documentation
};
constexpr openspace::properties::Property::PropertyInfo CollectStatsInfo = {
"CollectStats",
"Collect stats",
"" // @TODO Missing documentation
};
constexpr openspace::properties::Property::PropertyInfo LimitLevelInfo = {
"LimitLevelByAvailableData",
"Limit level by available data",
"" // @TODO Missing documentation
};
constexpr openspace::properties::Property::PropertyInfo ModelSpaceRenderingInfo = {
"ModelSpaceRenderingCutoffLevel",
"Model Space Rendering Cutoff Level",
"" // @TODO Missing documentation
};
constexpr openspace::properties::Property::PropertyInfo PerformShadingInfo = {
"PerformShading",
"Perform shading",
"" // @TODO Missing documentation
};
constexpr openspace::properties::Property::PropertyInfo AtmosphereInfo = {
"Atmosphere",
"Atmosphere",
"" // @TODO Missing documentation
};
constexpr openspace::properties::Property::PropertyInfo AccurateNormalsInfo = {
"UseAccurateNormals",
"Use Accurate Normals",
"" // @TODO Missing documentation
};
constexpr openspace::properties::Property::PropertyInfo EclipseInfo = {
"Eclipse",
"Eclipse",
"Enables/Disable Eclipse shadows"
};
constexpr openspace::properties::Property::PropertyInfo EclipseHardShadowsInfo = {
"EclipseHardShadows",
"Eclipse Hard Shadows",
"Enables the rendering of eclipse shadows using hard shadows"
};
constexpr openspace::properties::Property::PropertyInfo LodScaleFactorInfo = {
"LodScaleFactor",
"Level of Detail Scale Factor",
"" // @TODO Missing documentation
};
constexpr openspace::properties::Property::PropertyInfo CameraMinHeightInfo = {
"CameraMinHeight",
"Camera Minimum Height",
"" // @TODO Missing documentation
};
constexpr openspace::properties::Property::PropertyInfo OrenNayarRoughnessInfo = {
"OrenNayarRoughness",
"orenNayarRoughness",
"" // @TODO Missing documentation
};
} // namespace
using namespace openspace::properties;
namespace openspace::globebrowsing {
RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
: Renderable(dictionary)
, _debugProperties({
BoolProperty(SaveOrThrowInfo, false),
BoolProperty(ShowChunkEdgeInfo, false),
BoolProperty(ShowChunkBoundsInfo, false),
BoolProperty(ShowChunkAABBInfo, false),
BoolProperty(HeightResolutionInfo, false),
BoolProperty(HeightIntensityInfo, false),
BoolProperty(FrustumCullingInfo, true),
BoolProperty(HorizonCullingInfo, true),
BoolProperty(LevelProjectedAreaInfo, false),
BoolProperty(ResetTileProviderInfo, false),
BoolProperty(CollectStatsInfo, false),
BoolProperty(LimitLevelInfo, true),
IntProperty(ModelSpaceRenderingInfo, 10, 1, 22)
})
, _generalProperties({
BoolProperty(PerformShadingInfo, true),
BoolProperty(AtmosphereInfo, false),
BoolProperty(AccurateNormalsInfo, false),
BoolProperty(EclipseInfo, false),
BoolProperty(EclipseHardShadowsInfo, false),
FloatProperty(LodScaleFactorInfo, 10.f, 1.f, 50.f),
FloatProperty(CameraMinHeightInfo, 100.f, 0.f, 1000.f),
FloatProperty(OrenNayarRoughnessInfo, 0.f, 0.f, 1.f)
})
, _debugPropertyOwner({ "Debug" })
{
setIdentifier("RenderableGlobe");
dictionary.getValue(keyFrame, _frame);
// Read the radii in to its own dictionary
if (dictionary.hasKeyAndValue<glm::dvec3>(keyRadii)) {
const glm::dvec3 radii = dictionary.value<glm::vec3>(keyRadii);
_ellipsoid = Ellipsoid(radii);
setBoundingSphere(static_cast<float>(_ellipsoid.maximumRadius()));
}
else if (dictionary.hasKeyAndValue<double>(keyRadii)) {
const double radius = dictionary.value<double>(keyRadii);
_ellipsoid = Ellipsoid({ radius, radius, radius });
setBoundingSphere(static_cast<float>(_ellipsoid.maximumRadius()));
}
// Ghoul can't read ints from lua dictionaries...
double patchSegmentsd;
dictionary.getValue(keySegmentsPerPatch, patchSegmentsd);
int patchSegments = static_cast<int>(patchSegmentsd);
if (dictionary.hasValue<bool>("PerformShading")) {
_generalProperties.performShading = dictionary.value<bool>("PerformShading");
}
// Init layer manager
ghoul::Dictionary layersDictionary;
if (!dictionary.getValue(keyLayers, layersDictionary)) {
throw ghoul::RuntimeError(std::string(keyLayers) + " must be specified");
}
_layerManager = std::make_shared<LayerManager>(layersDictionary);
_chunkedLodGlobe = std::make_unique<ChunkedLodGlobe>(
*this,
patchSegments,
_layerManager,
_ellipsoid
);
//_pointGlobe = std::make_shared<PointGlobe>(*this);
//_distanceSwitch.addSwitchValue(_chunkedLodGlobe);
//_distanceSwitch.addSwitchValue(_pointGlobe);
addProperty(_generalProperties.atmosphereEnabled);
addProperty(_generalProperties.performShading);
addProperty(_generalProperties.useAccurateNormals);
addProperty(_generalProperties.eclipseShadowsEnabled);
addProperty(_generalProperties.eclipseHardShadows);
addProperty(_generalProperties.lodScaleFactor);
addProperty(_generalProperties.cameraMinHeight);
addProperty(_generalProperties.orenNayarRoughness);
_debugPropertyOwner.addProperty(_debugProperties.saveOrThrowCamera);
_debugPropertyOwner.addProperty(_debugProperties.showChunkEdges);
_debugPropertyOwner.addProperty(_debugProperties.showChunkBounds);
_debugPropertyOwner.addProperty(_debugProperties.showChunkAABB);
_debugPropertyOwner.addProperty(_debugProperties.showHeightResolution);
_debugPropertyOwner.addProperty(_debugProperties.showHeightIntensities);
_debugPropertyOwner.addProperty(_debugProperties.performFrustumCulling);
_debugPropertyOwner.addProperty(_debugProperties.performHorizonCulling);
_debugPropertyOwner.addProperty(
_debugProperties.levelByProjectedAreaElseDistance
);
_debugPropertyOwner.addProperty(_debugProperties.resetTileProviders);
_debugPropertyOwner.addProperty(_debugProperties.collectStats);
_debugPropertyOwner.addProperty(_debugProperties.limitLevelByAvailableData);
_debugPropertyOwner.addProperty(_debugProperties.modelSpaceRenderingCutoffLevel);
auto notifyShaderRecompilation = [&](){
_chunkedLodGlobe->notifyShaderRecompilation();
};
_generalProperties.atmosphereEnabled.onChange(notifyShaderRecompilation);
_generalProperties.useAccurateNormals.onChange(notifyShaderRecompilation);
_generalProperties.eclipseShadowsEnabled.onChange(notifyShaderRecompilation);
_generalProperties.eclipseHardShadows.onChange(notifyShaderRecompilation);
_generalProperties.performShading.onChange(notifyShaderRecompilation);
_debugProperties.showChunkEdges.onChange(notifyShaderRecompilation);
_debugProperties.showHeightResolution.onChange(notifyShaderRecompilation);
_debugProperties.showHeightIntensities.onChange(notifyShaderRecompilation);
_layerManager->onChange(notifyShaderRecompilation);
addPropertySubOwner(_debugPropertyOwner);
addPropertySubOwner(_layerManager.get());
//addPropertySubOwner(_pointGlobe.get());
//================================================================
//======== Reads Shadow (Eclipses) Entries in mod file ===========
//================================================================
ghoul::Dictionary shadowDictionary;
bool success = dictionary.getValue(keyShadowGroup, shadowDictionary);
bool disableShadows = false;
if (success) {
std::vector<std::pair<std::string, double>> sourceArray;
unsigned int sourceCounter = 1;
while (success) {
std::string sourceName;
success = shadowDictionary.getValue(keyShadowSource +
std::to_string(sourceCounter) + ".Name", sourceName);
if (success) {
double sourceRadius;
success = shadowDictionary.getValue(keyShadowSource +
std::to_string(sourceCounter) + ".Radius", sourceRadius);
if (success) {
sourceArray.emplace_back(sourceName, sourceRadius);
}
else {
//LWARNING("No Radius value expecified for Shadow Source Name "
// << sourceName << " from " << name
// << " planet.\nDisabling shadows for this planet.");
disableShadows = true;
break;
}
}
sourceCounter++;
}
if (!disableShadows && !sourceArray.empty()) {
success = true;
std::vector<std::pair<std::string, double>> casterArray;
unsigned int casterCounter = 1;
while (success) {
std::string casterName;
success = shadowDictionary.getValue(keyShadowCaster +
std::to_string(casterCounter) + ".Name", casterName);
if (success) {
double casterRadius;
success = shadowDictionary.getValue(keyShadowCaster +
std::to_string(casterCounter) + ".Radius", casterRadius);
if (success) {
casterArray.emplace_back(casterName, casterRadius);
}
else {
//LWARNING("No Radius value expecified for Shadow Caster Name "
// << casterName << " from " << name
// << " planet.\nDisabling shadows for this planet.");
disableShadows = true;
break;
}
}
casterCounter++;
}
std::vector<Ellipsoid::ShadowConfiguration> shadowConfArray;
if (!disableShadows && (!sourceArray.empty() && !casterArray.empty())) {
for (const auto & source : sourceArray) {
for (const auto & caster : casterArray) {
Ellipsoid::ShadowConfiguration sc;
sc.source = source;
sc.caster = caster;
shadowConfArray.push_back(sc);
}
}
_ellipsoid.setShadowConfigurationArray(shadowConfArray);
}
}
}
}
void RenderableGlobe::initializeGL() {
_layerManager->initialize();
_layerManager->update();
_chunkedLodGlobe->initializeGL();
// Recompile the shaders directly so that it is not done the first time the render
// function is called.
_chunkedLodGlobe->recompileShaders();
}
void RenderableGlobe::deinitializeGL() {
_chunkedLodGlobe->deinitializeGL();
_layerManager->deinitialize();
}
bool RenderableGlobe::isReady() const {
return true;
}
void RenderableGlobe::render(const RenderData& data, RendererTasks& rendererTask) {
bool statsEnabled = _debugProperties.collectStats;
#ifdef DEBUG_GLOBEBROWSING_STATSRECORD
_chunkedLodGlobe->stats.setEnabled(statsEnabled);
#else // DEBUG_GLOBEBROWSING_STATSRECORD
if (statsEnabled) {
LWARNINGC(
"RenderableGlobe",
"Stats collection was enabled, but ChunkedLodGlobe compiled without support"
);
_debugProperties.collectStats = false;
}
#endif // DEBUG_GLOBEBROWSING_STATSRECORD
if (_enabled) {
if (_debugProperties.saveOrThrowCamera.value()) {
_debugProperties.saveOrThrowCamera.setValue(false);
if (savedCamera() == nullptr) { // save camera
setSaveCamera(std::make_shared<Camera>(data.camera));
}
else { // throw camera
setSaveCamera(nullptr);
}
}
const double distanceToCamera = distance(
data.camera.positionVec3(),
data.modelTransform.translation
);
// This distance will be enough to render the globe as one pixel if the field of
// view is 'fov' radians and the screen resolution is 'res' pixels.
const double fov = 2 * glm::pi<double>() / 6; // 60 degrees
const int res = 2880;
const double distance = res * _chunkedLodGlobe->boundingSphere() / tan(fov / 2);
if (distanceToCamera < distance) {
_chunkedLodGlobe->render(data, rendererTask);
}
}
if (_savedCamera != nullptr) {
DebugRenderer::ref().renderCameraFrustum(data, *_savedCamera);
}
}
void RenderableGlobe::update(const UpdateData& data) {
_time = data.time.j2000Seconds();
_chunkedLodGlobe->update(data);
glm::dmat4 translation =
glm::translate(glm::dmat4(1.0), data.modelTransform.translation);
glm::dmat4 rotation = glm::dmat4(data.modelTransform.rotation);
glm::dmat4 scaling =
glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale,
data.modelTransform.scale, data.modelTransform.scale));
_cachedModelTransform = translation * rotation * scaling;
_cachedInverseModelTransform = glm::inverse(_cachedModelTransform);
if (_debugProperties.resetTileProviders) {
_layerManager->reset();
_debugProperties.resetTileProviders = false;
}
_layerManager->update();
_chunkedLodGlobe->update(data);
}
glm::dvec3 RenderableGlobe::projectOnEllipsoid(glm::dvec3 position) {
return _ellipsoid.geodeticSurfaceProjection(position);
}
float RenderableGlobe::getHeight(glm::dvec3 position) const {
if (_chunkedLodGlobe) {
return _chunkedLodGlobe->getHeight(position);
}
else {
return 0;
}
}
ChunkedLodGlobe* RenderableGlobe::chunkedLodGlobe() const{
return _chunkedLodGlobe.get();
}
LayerManager* RenderableGlobe::layerManager() const {
return _layerManager.get();
}
const Ellipsoid& RenderableGlobe::ellipsoid() const{
return _ellipsoid;
}
const glm::dmat4& RenderableGlobe::modelTransform() const{
return _cachedModelTransform;
}
const glm::dmat4& RenderableGlobe::inverseModelTransform() const{
return _cachedInverseModelTransform;
}
const RenderableGlobe::DebugProperties&
RenderableGlobe::debugProperties() const{
return _debugProperties;
}
const RenderableGlobe::GeneralProperties&
RenderableGlobe::generalProperties() const{
return _generalProperties;
}
const std::shared_ptr<const Camera> RenderableGlobe::savedCamera() const {
return _savedCamera;
}
SurfacePositionHandle RenderableGlobe::calculateSurfacePositionHandle(
const glm::dvec3& targetModelSpace) const
{
glm::dvec3 centerToEllipsoidSurface =
_ellipsoid.geodeticSurfaceProjection(targetModelSpace);
glm::dvec3 ellipsoidSurfaceToTarget = targetModelSpace - centerToEllipsoidSurface;
// ellipsoidSurfaceOutDirection will point towards the target, we want the outward
// direction. Therefore it must be flipped in case the target is under the reference
// ellipsoid so that it always points outwards
glm::dvec3 ellipsoidSurfaceOutDirection = glm::normalize(ellipsoidSurfaceToTarget);
if (glm::dot(ellipsoidSurfaceOutDirection, centerToEllipsoidSurface) < 0) {
ellipsoidSurfaceOutDirection *= -1.0;
}
double heightToSurface = getHeight(targetModelSpace);
heightToSurface = glm::isnan(heightToSurface) ? 0.0 : heightToSurface;
centerToEllipsoidSurface = glm::isnan(glm::length(centerToEllipsoidSurface)) ?
(glm::dvec3(0.0, 1.0, 0.0) * static_cast<double>(boundingSphere())) :
centerToEllipsoidSurface;
ellipsoidSurfaceOutDirection = glm::isnan(glm::length(ellipsoidSurfaceOutDirection)) ?
glm::dvec3(0.0, 1.0, 0.0) : ellipsoidSurfaceOutDirection;
return {
centerToEllipsoidSurface,
ellipsoidSurfaceOutDirection,
heightToSurface
};
}
void RenderableGlobe::setSaveCamera(std::shared_ptr<Camera> camera) {
_savedCamera = std::move(camera);
}
} // namespace openspace::globebrowsing

View File

@@ -1,149 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___RENDERABLEGLOBE___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___RENDERABLEGLOBE___H__
#include <openspace/rendering/renderable.h>
#include <modules/globebrowsing/geometry/ellipsoid.h>
//#include <modules/globebrowsing/other/distanceswitch.h>
#include <openspace/properties/scalar/floatproperty.h>
#include <openspace/properties/scalar/intproperty.h>
#include <openspace/properties/scalar/boolproperty.h>
#ifdef OPENSPACE_MODULE_ATMOSPHERE_ENABLED
namespace openspace {
class AtmosphereDeferredcaster;
}
#endif
namespace openspace::globebrowsing {
class ChunkedLodGlobe;
class PointGlobe;
class LayerManager;
/**
* A RenderableGlobe is a globe modeled as an ellipsoid using a chunked LOD algorithm for
* rendering.
*/
class RenderableGlobe : public Renderable {
public:
/**
* These properties are specific for <code>ChunkedLodGlobe</code> and separated from
* the general properties of <code>RenderableGlobe</code>.
*/
struct DebugProperties {
properties::BoolProperty saveOrThrowCamera;
properties::BoolProperty showChunkEdges;
properties::BoolProperty showChunkBounds;
properties::BoolProperty showChunkAABB;
properties::BoolProperty showHeightResolution;
properties::BoolProperty showHeightIntensities;
properties::BoolProperty performFrustumCulling;
properties::BoolProperty performHorizonCulling;
properties::BoolProperty levelByProjectedAreaElseDistance;
properties::BoolProperty resetTileProviders;
properties::BoolProperty collectStats;
properties::BoolProperty limitLevelByAvailableData;
properties::IntProperty modelSpaceRenderingCutoffLevel;
};
struct GeneralProperties {
properties::BoolProperty performShading;
properties::BoolProperty atmosphereEnabled;
properties::BoolProperty useAccurateNormals;
properties::BoolProperty eclipseShadowsEnabled;
properties::BoolProperty eclipseHardShadows;
properties::FloatProperty lodScaleFactor;
properties::FloatProperty cameraMinHeight;
properties::FloatProperty orenNayarRoughness;
};
// Shadow structure
struct ShadowRenderingStruct {
double xu;
double xp;
double rs;
double rc;
glm::dvec3 sourceCasterVec;
glm::dvec3 casterPositionVec;
bool isShadowing;
};
RenderableGlobe(const ghoul::Dictionary& dictionary);
~RenderableGlobe() = default;
void initializeGL() override;
void deinitializeGL() override;
bool isReady() const override;
void render(const RenderData& data, RendererTasks& rendererTask) override;
void update(const UpdateData& data) override;
// Getters that perform calculations
glm::dvec3 projectOnEllipsoid(glm::dvec3 position);
float getHeight(glm::dvec3 position) const;
// Getters
ChunkedLodGlobe* chunkedLodGlobe() const;
LayerManager* layerManager() const;
const Ellipsoid& ellipsoid() const;
const glm::dmat4& modelTransform() const;
const glm::dmat4& inverseModelTransform() const;
const DebugProperties& debugProperties() const;
const GeneralProperties& generalProperties() const;
const std::shared_ptr<const Camera> savedCamera() const;
double interactionDepthBelowEllipsoid();
// Setters
void setSaveCamera(std::shared_ptr<Camera> camera);
virtual SurfacePositionHandle calculateSurfacePositionHandle(
const glm::dvec3& targetModelSpace) const override;
private:
std::unique_ptr<ChunkedLodGlobe> _chunkedLodGlobe;
Ellipsoid _ellipsoid;
std::shared_ptr<LayerManager> _layerManager;
std::shared_ptr<Camera> _savedCamera;
std::string _frame;
double _time = 0.0;
glm::dmat4 _cachedModelTransform;
glm::dmat4 _cachedInverseModelTransform;
// Properties
DebugProperties _debugProperties;
GeneralProperties _generalProperties;
properties::PropertyOwner _debugPropertyOwner;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___RENDERABLEGLOBE___H__

View File

@@ -1,171 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/meshes/basicgrid.h>
#include <ghoul/glm.h>
#include <ghoul/misc/assert.h>
namespace openspace::globebrowsing {
BasicGrid::BasicGrid(unsigned int xSegments, unsigned int ySegments,
TriangleSoup::Positions usePositions,
TriangleSoup::TextureCoordinates useTextureCoordinates,
TriangleSoup::Normals useNormals)
: Grid(xSegments, ySegments)
{
_geometry = std::make_unique<TriangleSoup>(
createElements(xSegments, ySegments),
usePositions,
useTextureCoordinates,
useNormals
);
if (usePositions) {
_geometry->setVertexPositions(createPositions(_xSegments, _ySegments));
}
if (useTextureCoordinates) {
_geometry->setVertexTextureCoordinates(
createTextureCoordinates(_xSegments, _ySegments)
);
}
if (useNormals) {
_geometry->setVertexNormals(createNormals(_xSegments, _ySegments));
}
}
int BasicGrid::xSegments() const {
return _xSegments;
}
int BasicGrid::ySegments() const {
return _ySegments;
}
void BasicGrid::validate([[maybe_unused]] int xSegments, [[maybe_unused]] int ySegments) {
ghoul_assert(
xSegments > 0 && ySegments > 0,
std::string("Resolution must be at least 1x1. (") +
std::to_string(xSegments) + ", " + std::to_string(ySegments) + ")"
);
}
inline size_t BasicGrid::numElements(int xSegments, int ySegments) {
return 3 * 2 * xSegments * ySegments;
}
inline size_t BasicGrid::numVertices(int xSegments, int ySegments) {
return (xSegments + 1) * (ySegments + 1);
}
std::vector<GLuint> BasicGrid::createElements(int xSegments, int ySegments) {
validate(xSegments, ySegments);
std::vector<GLuint> elements;
elements.reserve(numElements(xSegments, ySegments));
for (int y = 0; y < ySegments; y++) {
for (int x = 0; x < xSegments; x++) {
// x v01---v11 x ..
// | / |
// x v00---v10 x ..
//
// x x x x ..
// : : : :
const GLuint v00 = (y + 0) * (xSegments + 1) + x + 0;
const GLuint v10 = (y + 0) * (xSegments + 1) + x + 1;
const GLuint v01 = (y + 1) * (xSegments + 1) + x + 0;
const GLuint v11 = (y + 1) * (xSegments + 1) + x + 1;
// add upper triangle
elements.push_back(v00);
elements.push_back(v10);
elements.push_back(v11);
// add lower triangle
elements.push_back(v00);
elements.push_back(v11);
elements.push_back(v01);
}
}
return elements;
}
std::vector<glm::vec4> BasicGrid::createPositions(int xSegments, int ySegments) {
validate(xSegments, ySegments);
std::vector<glm::vec4> positions;
positions.reserve(numVertices(xSegments, ySegments));
// Copy from 2d texture coordinates and use as template to create positions
std::vector<glm::vec2> templateTextureCoords = createTextureCoordinates(
xSegments,
ySegments
);
for (const glm::vec2& coords : templateTextureCoords) {
positions.emplace_back(coords, 0.f, 1.f);
}
//for (unsigned int i = 0; i < templateTextureCoords.size(); i++) {
// positions.push_back(glm::vec4(
// templateTextureCoords[i],
// 0.0f,
// 1.0f
// ));
//}
return positions;
}
std::vector<glm::vec2> BasicGrid::createTextureCoordinates(int xSegments, int ySegments) {
validate(xSegments, ySegments);
std::vector<glm::vec2> textureCoordinates;
textureCoordinates.reserve(numVertices(xSegments, ySegments));
for (int y = 0; y < ySegments + 1; y++) {
for (int x = 0; x < xSegments + 1; x++) {
textureCoordinates.emplace_back(
static_cast<float>(x) / static_cast<float>(xSegments),
static_cast<float>(y) / static_cast<float>(ySegments)
);
}
}
return textureCoordinates;
}
std::vector<glm::vec3> BasicGrid::createNormals(int xSegments, int ySegments) {
validate(xSegments, ySegments);
std::vector<glm::vec3> normals;
normals.reserve(numVertices(xSegments, ySegments));
for (int y = 0; y < ySegments + 1; y++) {
for (int x = 0; x < xSegments + 1; x++) {
normals.emplace_back(0.f, 0.f, 1.f);
}
}
return normals;
}
} // namespace openspace::globebrowsing

View File

@@ -1,70 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___BASICGRIDGEOMETRY___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___BASICGRIDGEOMETRY___H__
#include <modules/globebrowsing/meshes/grid.h>
#include <modules/globebrowsing/meshes/trianglesoup.h>
#include <vector>
namespace openspace::globebrowsing {
class BasicGrid : public Grid {
public:
/**
* \param xSegments is the number of grid cells in the x direction.
* \param ySegments is the number of grid cells in the y direction.
* \param usePositions determines whether or not to upload any vertex position data
* to the GPU.
* \param useTextureCoordinates determines whether or not to upload any vertex texture
* coordinate data to the GPU.
* \param useNormals determines whether or not to upload any vertex normal data
* to the GPU.
*/
BasicGrid(unsigned int xSegments, unsigned int ySegments,
TriangleSoup::Positions usePositions,
TriangleSoup::TextureCoordinates useTextureCoordinates,
TriangleSoup::Normals useNormals);
virtual int xSegments() const override;
virtual int ySegments() const override;
private:
std::vector<GLuint> createElements(int xSegments, int ySegments) override;
std::vector<glm::vec4> createPositions(int xSegments, int ySegments) override;
std::vector<glm::vec2> createTextureCoordinates(int xSegments,
int ySegments) override;
std::vector<glm::vec3> createNormals(int xSegments, int ySegments) override;
void validate(int xSegments, int ySegments);
inline size_t numElements(int xSegments, int ySegments);
inline size_t numVertices(int xSegments, int ySegments);
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___BASICGRIDGEOMETRY___H__

View File

@@ -1,101 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___GRIDGEOMETRY___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___GRIDGEOMETRY___H__
#include <ghoul/glm.h>
#include <ghoul/opengl/ghoul_gl.h>
#include <memory>
#include <vector>
namespace openspace::globebrowsing {
class TriangleSoup;
/**
* Abstract class defining an interface used for geometries with grid structures.
* The class Grid should be extended for use of geometries with a 2D structure where the
* number of segments in x and y direction represents the number of vertices + 1 in each
* direction.
*/
class Grid {
public:
Grid(int xSegments, int ySegments);
virtual ~Grid();
TriangleSoup& geometry();
/**
* Returns the number of grid cells in the x direction. Hence the number of vertices
* in the x direction is xResolution + 1.
*/
virtual int xSegments() const = 0;
/**
* Returns the number of grid cells in the y direction. Hence the number of vertices
* in the y direction is xResolution + 1.
*/
virtual int ySegments() const = 0;
protected:
/**
* Should return the indices of vertices for a grid with size \c xSegments *
* \c ySegments. Where the number of vertices in each direction is the number of
* segments + 1.
*/
virtual std::vector<GLuint> createElements(int xSegments, int ySegments) = 0;
/**
* Should return the positions of vertices for a grid with size \c xSegments *
* \c ySegments. Where the number of vertices in each direction is the number of
* segments + 1.
*/
virtual std::vector<glm::vec4> createPositions(int xSegments, int ySegments) = 0;
/**
* Should return the texture coordinates of vertices for a grid with size
* \c xSegments * \c ySegments. Where the number of vertices in each direction is the
* number of segments + 1.
*/
virtual std::vector<glm::vec2> createTextureCoordinates(int xSegments,
int ySegments) = 0;
/**
* Should return the normals of vertices for a grid with size \c xSegments *
* \c ySegments. Where the number of vertices in each direction is the number of
* segments + 1.
*/
virtual std::vector<glm::vec3> createNormals(int xSegments, int ySegments) = 0;
std::unique_ptr<TriangleSoup> _geometry;
const int _xSegments;
const int _ySegments;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___GRIDGEOMETRY___H__

View File

@@ -1,174 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/meshes/skirtedgrid.h>
#include <ghoul/misc/assert.h>
namespace {
size_t numElements(int xSegments, int ySegments) {
return 3 * 2 * xSegments * ySegments;
}
size_t numVertices(int xSegments, int ySegments) {
return (xSegments + 1) * (ySegments + 1);
}
void validate([[maybe_unused]] int xSegments, [[maybe_unused]] int ySegments) {
ghoul_assert(
xSegments > 0 && ySegments > 0,
"Resolution must be at least 1x1. (" + std::to_string(xSegments) + ", " +
std::to_string(ySegments) + ")"
);
}
} // namespace
namespace openspace::globebrowsing {
SkirtedGrid::SkirtedGrid(unsigned int xSegments, unsigned int ySegments,
TriangleSoup::Positions usePositions,
TriangleSoup::TextureCoordinates useTextureCoordinates,
TriangleSoup::Normals useNormals)
: Grid(xSegments, ySegments)
{
_geometry = std::make_unique<TriangleSoup>(
createElements(xSegments, ySegments),
usePositions,
useTextureCoordinates,
useNormals
);
if (usePositions) {
_geometry->setVertexPositions(createPositions(_xSegments, _ySegments));
}
if (useTextureCoordinates) {
_geometry->setVertexTextureCoordinates(
createTextureCoordinates(_xSegments, _ySegments)
);
}
if (useNormals) {
_geometry->setVertexNormals(createNormals(_xSegments, _ySegments));
}
}
int SkirtedGrid::xSegments() const {
return _xSegments;
}
int SkirtedGrid::ySegments() const {
return _ySegments;
}
std::vector<GLuint> SkirtedGrid::createElements(int xSegments, int ySegments) {
validate(xSegments, ySegments);
std::vector<GLuint> elements;
elements.reserve(numElements(xSegments + 2, ySegments + 2));
for (int y = 0; y < ySegments + 2; y++) {
for (int x = 0; x < xSegments + 2; x++) {
// x v01---v11 x ..
// | / |
// x v00---v10 x ..
//
// x x x x ..
// : : : :
const GLuint v00 = (y + 0) * (xSegments + 2 + 1) + x + 0;
const GLuint v10 = (y + 0) * (xSegments + 2 + 1) + x + 1;
const GLuint v01 = (y + 1) * (xSegments + 2 + 1) + x + 0;
const GLuint v11 = (y + 1) * (xSegments + 2 + 1) + x + 1;
// add upper triangle
elements.push_back(v00);
elements.push_back(v10);
elements.push_back(v11);
// add lower triangle
elements.push_back(v00);
elements.push_back(v11);
elements.push_back(v01);
}
}
return elements;
}
std::vector<glm::vec4> SkirtedGrid::createPositions(int xSegments, int ySegments) {
validate(xSegments, ySegments);
// Copy from 2d texture coordinates and use as template to create positions
const std::vector<glm::vec2>& templateTextureCoords = createTextureCoordinates(
xSegments,
ySegments
);
std::vector<glm::vec4> positions;
positions.reserve(numVertices(xSegments, ySegments));
for (const glm::vec2& c : templateTextureCoords) {
positions.emplace_back(c, 0.f, 1.f);
}
return positions;
}
std::vector<glm::vec2> SkirtedGrid::createTextureCoordinates(int xSegments, int ySegments)
{
validate(xSegments, ySegments);
std::vector<glm::vec2> textureCoordinates;
textureCoordinates.reserve(numVertices(xSegments + 2, ySegments + 2));
for (int y = -1; y < ySegments + 2; y++) {
for (int x = -1; x < xSegments + 2; x++) {
textureCoordinates.emplace_back(
glm::clamp(
static_cast<float>(x) / static_cast<float>(xSegments),
0 - 1.f / (2 * xSegments),
1 + 1.f / (2 * xSegments)
),
glm::clamp(
static_cast<float>(y) / static_cast<float>(ySegments),
0 - 1.f / (2 * ySegments),
1 + 1.f / (2 * ySegments)
)
);
}
}
return textureCoordinates;
}
std::vector<glm::vec3> SkirtedGrid::createNormals(int xSegments, int ySegments) {
validate(xSegments, ySegments);
std::vector<glm::vec3> normals;
normals.reserve(numVertices(xSegments + 2, ySegments + 2));
for (int y = -1; y < ySegments + 2; y++) {
for (int x = -1; x < xSegments + 2; x++) {
normals.emplace_back(0.f, 0.f, 1.f);
}
}
return normals;
}
} // namespace openspace::globebrowsing

View File

@@ -1,182 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/meshes/trianglesoup.h>
#include <ghoul/logging/logmanager.h>
namespace {
constexpr const char* _loggerCat = "TriangleSoup";
} // namespace
namespace openspace::globebrowsing {
TriangleSoup::TriangleSoup(std::vector<unsigned int> elements, Positions usePositions,
TextureCoordinates useTextures, Normals useNormals)
: _useVertexPositions(usePositions)
, _useTextureCoordinates(useTextures)
, _useVertexNormals(useNormals)
{
setElements(std::move(elements));
}
TriangleSoup::~TriangleSoup() {
glDeleteBuffers(1, &_vertexBufferID);
glDeleteBuffers(1, &_elementBufferID);
glDeleteVertexArrays(1, &_vaoID);
}
void TriangleSoup::setVertexPositions(std::vector<glm::vec4> positions) {
_useVertexPositions = true;
_gpuDataNeedUpdate = true;
_vertexData.resize(positions.size());
for (size_t i = 0; i < positions.size(); ++i) {
_vertexData[i].position[0] = positions[i][0];
_vertexData[i].position[1] = positions[i][1];
_vertexData[i].position[2] = positions[i][2];
//_vertexData[i].position[3] = positions[i][3];
}
}
void TriangleSoup::setVertexTextureCoordinates(std::vector<glm::vec2> textures) {
_useTextureCoordinates = true;
_gpuDataNeedUpdate = true;
_vertexData.resize(textures.size());
for (size_t i = 0; i < textures.size(); ++i) {
_vertexData[i].texture[0] = textures[i][0];
_vertexData[i].texture[1] = textures[i][1];
}
}
void TriangleSoup::setVertexNormals(std::vector<glm::vec3> normals) {
_useVertexNormals = true;
_gpuDataNeedUpdate = true;
_vertexData.resize(normals.size());
for (size_t i = 0; i < normals.size(); ++i) {
_vertexData[i].normal[0] = normals[i][0];
_vertexData[i].normal[1] = normals[i][1];
_vertexData[i].normal[2] = normals[i][2];
}
}
void TriangleSoup::setElements(std::vector<unsigned int> elements) {
_gpuDataNeedUpdate = true;
_elementData = std::move(elements);
}
bool TriangleSoup::updateDataOnGPU() {
// Create VAO
if (_vaoID == 0) {
glGenVertexArrays(1, &_vaoID);
}
// Create VBOs
if (_vertexBufferID == 0 && !_vertexData.empty()) {
glGenBuffers(1, &_vertexBufferID);
if (_vertexBufferID == 0) {
LERROR("Could not create vertex buffer");
return false;
}
}
if (_elementBufferID == 0 && !_elementData.empty()) {
glGenBuffers(1, &_elementBufferID);
if (_elementBufferID == 0) {
LERROR("Could not create vertex element buffer");
return false;
}
}
// First VAO setup
glBindVertexArray(_vaoID);
// Vertex buffer
glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferID);
glBufferData(
GL_ARRAY_BUFFER,
_vertexData.size() * sizeof(Vertex),
&_vertexData[0],
GL_STATIC_DRAW
);
// Positions at location 0
if (_useVertexPositions) {
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), nullptr);
}
// Textures at location 1
if (_useTextureCoordinates) {
glEnableVertexAttribArray(1);
glVertexAttribPointer(
1,
2,
GL_FLOAT,
GL_FALSE,
sizeof(Vertex),
reinterpret_cast<const GLvoid*>(offsetof(Vertex, texture)) // NOLINT
);
}
// Normals at location 2
if (_useVertexNormals) {
glEnableVertexAttribArray(2);
glVertexAttribPointer(
2,
3,
GL_FLOAT,
GL_FALSE,
sizeof(Vertex),
reinterpret_cast<const GLvoid*>(offsetof(Vertex, normal)) // NOLINT
);
}
// Element buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _elementBufferID);
glBufferData(
GL_ELEMENT_ARRAY_BUFFER,
_elementData.size() * sizeof(GLint),
&_elementData[0],
GL_STATIC_DRAW);
glBindVertexArray(0);
_gpuDataNeedUpdate = false;
return true;
}
void TriangleSoup::drawUsingActiveProgram() {
if (_gpuDataNeedUpdate) {
updateDataOnGPU();
}
glBindVertexArray(_vaoID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _elementBufferID);
glDrawElements(
GL_TRIANGLES,
static_cast<GLsizei>(_elementData.size()),
GL_UNSIGNED_INT,
nullptr
);
glBindVertexArray(0);
}
} // namespace openspace::globebrowsing

View File

@@ -1,103 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___TRIANGLESOUP___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TRIANGLESOUP___H__
#include <ghoul/glm.h>
#include <ghoul/misc/boolean.h>
#include <ghoul/opengl/ghoul_gl.h>
#include <vector>
namespace openspace::globebrowsing {
/**
* Class to hold vertex data and handling OpenGL interfacing and rendering.
* A <code>TriangleSoup</code> has all data needed such as position buffer and normal
* buffer but all data is not necessarily needed for all purpouses so some vertex buffers
* such as normals can be disabled if not needed.
*/
// TODO : Possibly render triangle strips in this class instead of triangles since
// that is faster
class TriangleSoup {
public:
BooleanType(Positions);
BooleanType(TextureCoordinates);
BooleanType(Normals);
TriangleSoup(std::vector<unsigned int> elements, // At least elements are required
Positions usePositions = Positions::No,
TextureCoordinates useTextures = TextureCoordinates::No,
Normals useNormals = Normals::No);
~TriangleSoup();
// Setters
void setVertexPositions(std::vector<glm::vec4> positions);
void setVertexTextureCoordinates(std::vector<glm::vec2> textures);
void setVertexNormals(std::vector<glm::vec3> normals);
void setElements(std::vector<unsigned int> elements);
/**
* Calls OpenGL's draw function to draw the triangles defined in the vertex buffers
* using the current bound program object.
* The vertex buffer attribute input locations to the shader program comes in the
* order of positions (0), texture coordinates (1) and normals (2).
* The input locations in the shader program should be specified to match these
* locations.
*/
void drawUsingActiveProgram();
protected:
// Determines what attribute data is in use
bool _useVertexPositions;
bool _useTextureCoordinates;
bool _useVertexNormals;
struct Vertex {
GLfloat position[3];
GLfloat texture[2];
GLfloat normal[3];
};
// Vertex data
std::vector<Vertex> _vertexData;
std::vector<GLuint> _elementData;
private:
bool updateDataOnGPU();
// GL handles
GLuint _vaoID = 0;
GLuint _vertexBufferID = 0;
GLuint _elementBufferID = 0;
bool _gpuDataNeedUpdate = false;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TRIANGLESOUP___H__

View File

@@ -1,87 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/other/pixelbuffer.h>
#include <ghoul/logging/logmanager.h>
namespace {
constexpr const char* _loggerCat = "PixelBuffer";
} // namespace
namespace openspace::globebrowsing {
PixelBuffer::PixelBuffer(size_t numBytes, Usage usage)
: _numBytes(numBytes)
, _usage(usage)
{
glGenBuffers(1, &_id);
bind();
glBufferData(GL_PIXEL_UNPACK_BUFFER, _numBytes, nullptr, static_cast<GLenum>(_usage));
unbind();
}
PixelBuffer::~PixelBuffer() {
glDeleteBuffers(1, &_id);
}
void* PixelBuffer::mapBuffer(Access access) {
void* dataPtr = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, static_cast<GLenum>(access));
_isMapped = dataPtr != nullptr;
return dataPtr;
}
void* PixelBuffer::mapBufferRange(GLintptr offset, GLsizeiptr length,
BufferAccessMask access)
{
void* dataPtr = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, offset, length, access);
_isMapped = dataPtr;
return dataPtr;
}
bool PixelBuffer::unMapBuffer() {
GLboolean success = glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
if (!success) {
LERROR("Unable to unmap pixel buffer, data may be corrupt!");
}
_isMapped = false;
return success == GL_TRUE;
}
void PixelBuffer::bind() {
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _id);
}
void PixelBuffer::unbind() {
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
bool PixelBuffer::isMapped() const {
return _isMapped;
}
PixelBuffer::operator GLuint() const {
return _id;
}
} // namespace openspace::globebrowsing

View File

@@ -1,140 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___PIXEL_BUFFER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___PIXEL_BUFFER___H__
#include <ghoul/opengl/ghoul_gl.h>
namespace openspace::globebrowsing {
/**
* Handles an OpenGL pixel buffer which contains data allocated on the GPU. A simple
* class that wraps the standard functionality of OpenGL pixel buffer objects. Once
* the PixelBuffer is created, data is allocated on the GPU. When mapping data to a
* address pointer, the user needs to ensure the data is unmapped before the data can
* be used on the GPU / CPU depending on Usage.
*/
class PixelBuffer {
public:
/**
* All kinds of usage for pixel buffer objects as defined by the OpenGL standard.
* See: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBufferData.xhtml
*/
enum class Usage : std::underlying_type_t<GLenum> {
StreamDraw = static_cast<std::underlying_type_t<GLenum>>(GL_STREAM_DRAW),
StreamRead = static_cast<std::underlying_type_t<GLenum>>(GL_STREAM_READ),
StreamCopy = static_cast<std::underlying_type_t<GLenum>>(GL_STREAM_COPY),
StaticDraw = static_cast<std::underlying_type_t<GLenum>>(GL_STATIC_DRAW),
StaticRead = static_cast<std::underlying_type_t<GLenum>>(GL_STATIC_READ),
StaticCopy = static_cast<std::underlying_type_t<GLenum>>(GL_STATIC_COPY),
DynamicDraw = static_cast<std::underlying_type_t<GLenum>>(GL_DYNAMIC_DRAW),
DynamicRead = static_cast<std::underlying_type_t<GLenum>>(GL_DYNAMIC_READ),
DynamicCopy = static_cast<std::underlying_type_t<GLenum>>(GL_DYNAMIC_COPY)
};
/**
* Access hints for OpenGL buffer mapping
* See: https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glMapBuffer.xml
*/
enum class Access : std::underlying_type_t<GLenum> {
ReadOnly = static_cast<std::underlying_type_t<GLenum>>(GL_READ_ONLY),
WriteOnly = static_cast<std::underlying_type_t<GLenum>>(GL_WRITE_ONLY),
ReadWrite = static_cast<std::underlying_type_t<GLenum>>(GL_READ_WRITE)
};
/**
* Allocates <code>numBytes</code> bytes on the GPU and creates an ID for the pixel
* buffer object.
*
* \param numBytes is the number of bytes to be allocated on GPU memory
* \param usage is the Usage for the pixel buffer
*/
PixelBuffer(size_t numBytes, Usage usage);
/**
* calls glDeleteBuffers().
*/
~PixelBuffer();
/**
* Maps an address pointer to GPU direct memory access. The user must make sure the
* buffer is bound before calling this function.
*
* \param access is the access to which can be any of <code>GL_READ_ONLY</code>,
* <code>GL_WRITE_ONLY</code>, or <code>GL_READ_WRITE</code>
* \return The DMA address to the mapped buffer. Returns nullptr if the mapping
* failed
*/
void* mapBuffer(Access access);
/**
* Maps an address pointer to GPU direct memory access. Gives access to a range of
* the buffer. The user must make sure the buffer is bound before calling this
* function.
*
* \param offet is the number of bytes to the first address to get in the buffer
* \param length is the number of bytes to access in the buffer
* \param access is a bitfield describing the access as described in:
* https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glMapBufferRange.xhtml
* \return The DMA address to the mapped buffer. Returns nullptr if the mapping
* failed
*/
void* mapBufferRange(GLintptr offset, GLsizeiptr length, BufferAccessMask access);
/**
* Maps the default buffer and makes the data available on the GPU
*/
bool unMapBuffer();
/**
* Calls glBindBuffer()
*/
void bind();
/**
* Calls glBindBuffer() with argument 0 to unmap any pixel buffer
*/
void unbind();
/**
* \returns true of the buffer is mapped, otherwise false
*/
bool isMapped() const;
/**
* \returns the OpenGL id of the pixel buffer object
*/
operator GLuint() const;
private:
GLuint _id = 0;
const size_t _numBytes;
const Usage _usage;
bool _isMapped = false;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___PIXEL_BUFFER___H__

View File

@@ -1,116 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___PIXEL_BUFFER_CONTAINER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___PIXEL_BUFFER_CONTAINER___H__
#include <modules/globebrowsing/other/pixelbuffer.h>
#include <map>
namespace openspace::globebrowsing {
/**
* Templated class which owns one or many PixelBuffer%s. The KeyType is used to map a
* pixel buffer but only if it is not already mapped.
*/
template <class KeyType>
class PixelBufferContainer {
public:
/**
* Creates numPixelBuffers pixel buffer objects, each with numBytesPerBuffer bytes
* allocated on the GPU.
*
* \param numBytesPerBuffer is the number of bytes per pixel buffer. All pixel
* buffers within a <code>PixelBufferContainer</code> have the same number of
* bytes
* \param usage is the <code>Usage</code> as described by <code>PixelBuffer</code>
* \param numPixelBuffers is the number of pixel buffers to create for this container.
* If numPixelBuffers is omitted, no pixel buffers are created.
*/
PixelBufferContainer(size_t numBytesPerBuffer,
globebrowsing::PixelBuffer::Usage usage, size_t numPixelBuffers = 0);
~PixelBufferContainer() = default;
/**
* Finds a Pixel buffer and maps it if it is available.
*
* \param key is the identifier for the pixel buffer which can be used later when
* unmapping the mapped pixel buffer.
* \param access is the access as described by <code>PixelBuffer</code>
* \return An address pointer to DMA if the mapping succeeded. Otherwise a \c nullptr
* is returned. The mapping can fail if the buffer identified with \p key is
* already mapped or if something else failed.
*/
void* mapBuffer(KeyType key, PixelBuffer::Access access);
/**
* Finds a Pixel buffer and maps a range of it if it is available.
*
* \param key is the identifier for the pixel buffer which can be used later when
* unmapping the mapped pixel buffer.
* \param offet is the number of bytes to the first address to get in the buffer
* \param length is the number of bytes to access in the buffer
* \param access is the access as described by <code>PixelBuffer</code>
* \return An address pointer to DMA if the mapping succeeded. Otherwise a nullptr
* is returned. The mapping can fail if the buffer identified with \p key is
* already mapped or if something else failed.
*/
void* mapBufferRange(KeyType key, GLintptr offset, GLsizeiptr length,
BufferAccessMask access);
/**
* Unmaps all buffers in the PixelBufferContainer.
*
* \return \c true if the unmapping succeeded, otherwise \c false
*/
bool resetMappedBuffers();
/**
* Unmaps a buffer that has previously been mapped. This buffer is identified using
* \p key.
*
* \param key is the identifier of the mapped buffer.
* \return \c true if the unmapping succeeded, otherwise \c false
*/
bool unMapBuffer(KeyType key);
/**
* \return The \c GLuint id of a pixel buffer identified by \p key if it currently is
* mapped.
*/
GLuint idOfMappedBuffer(KeyType key);
private:
const globebrowsing::PixelBuffer::Usage _usage;
std::vector<std::unique_ptr<PixelBuffer>> _pixelBuffers;
// Maps from KeyType to index of mapped buffers
std::map<KeyType, int> _indexMap;
};
} // namespace openspace::globebrowsing
#include "pixelbuffercontainer.inl"
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___PIXEL_BUFFER_CONTAINER___H__

View File

@@ -1,129 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
namespace openspace::globebrowsing {
template <class KeyType>
PixelBufferContainer<KeyType>::PixelBufferContainer(size_t numBytesPerBuffer,
PixelBuffer::Usage usage, size_t numPixelBuffers)
: _usage(usage)
{
for (size_t i = 0; i < numPixelBuffers; ++i) {
_pixelBuffers.push_back(std::make_unique<PixelBuffer>(numBytesPerBuffer, _usage));
}
}
template <class KeyType>
void* PixelBufferContainer<KeyType>::mapBuffer(KeyType key, PixelBuffer::Access access) {
const typename std::map<KeyType, int>::const_iterator iter = _indexMap.find(key);
const bool notFoundAmongMappedBuffers = (iter == _indexMap.end());
if (!notFoundAmongMappedBuffers) { // This PBO is already mapped
ghoul_assert(_pixelBuffers[iter->second], "Incorrect index map");
return nullptr;
}
// Find a pixel buffer that is unmapped
for (size_t i = 0; i < _pixelBuffers.size(); ++i) {
if (!_pixelBuffers[i]->isMapped()) {
_pixelBuffers[i]->bind();
void* dataPtr = _pixelBuffers[i]->mapBuffer(access);
_pixelBuffers[i]->unbind();
if (dataPtr) { // Success in mapping
// Add this index to the map of mapped pixel buffers
_indexMap.emplace(std::move(key), static_cast<int>(i));
return dataPtr;
}
}
}
return nullptr;
}
template <class KeyType>
void* PixelBufferContainer<KeyType>::mapBufferRange(KeyType key, GLintptr offset,
GLsizeiptr length,
BufferAccessMask access)
{
const typename std::map<KeyType, int>::const_iterator iter = _indexMap.find(key);
const bool notFoundAmongMappedBuffers = (iter == _indexMap.end());
if (!notFoundAmongMappedBuffers) { // This PBO is already mapped
ghoul_assert(_pixelBuffers[iter->second], "Incorrect index map");
return nullptr;
}
// Find a pixel buffer that is unmapped
for (int i = 0; i < _pixelBuffers.size(); ++i) {
const bool bufferIsMapped = _pixelBuffers[i]->isMapped();
if (!bufferIsMapped) {
_pixelBuffers[i]->bind();
void* dataPtr = _pixelBuffers[i]->mapBufferRange(offset, length, access);
_pixelBuffers[i]->unbind();
if (dataPtr) { // Success in mapping
_indexMap.emplace(std::move(key), i);
return dataPtr;
}
}
}
return nullptr;
}
template <class KeyType>
bool PixelBufferContainer<KeyType>::resetMappedBuffers() {
bool success = true;
for (auto iter = _indexMap.begin(); iter != _indexMap.end(); iter++) {
const int index = iter->second; // Index where the mapped buffer is stored
_pixelBuffers[index]->bind();
success &= _pixelBuffers[index]->unMapBuffer();
_pixelBuffers[index]->unbind();
_indexMap.erase(iter); // This key should no longer be among the mapped buffers
}
return success;
}
template <class KeyType>
bool PixelBufferContainer<KeyType>::unMapBuffer(KeyType key) {
bool success = false;
const typename std::map<KeyType, int>::const_iterator iter = _indexMap.find(key);
if (iter != _indexMap.end()) { // Found a mapped pixel buffer
const int index = iter->second; // Index where the mapped buffer is stored
_pixelBuffers[index]->bind();
success = _pixelBuffers[index]->unMapBuffer();
_pixelBuffers[index]->unbind();
_indexMap.erase(iter); // This key should no longer be among the mapped buffers
}
return success;
}
template <class KeyType>
GLuint PixelBufferContainer<KeyType>::idOfMappedBuffer(KeyType key) {
const typename std::map<KeyType, int>::const_iterator iter = _indexMap.find(key);
if (iter != _indexMap.end()) { // Found a mapped pixel buffer
int index = iter->second; // Index where the mapped buffer is stored
return *_pixelBuffers[index];
}
return 0;
}
} // namespace openspace::globebrowsing

View File

@@ -1,121 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/other/statscollector.h>
#include <ghoul/misc/assert.h>
#include <fstream>
#include <iomanip>
namespace openspace::globebrowsing {
StatsCollector::StatsCollector(std::string filename, int dumpEveryXRecord,
Enabled enabled, std::string delimiter)
: i(TemplatedStatsCollector<long long>(
TemplatedStatsCollector<long long>::Enabled(enabled),
delimiter
))
, d(TemplatedStatsCollector<double>(
TemplatedStatsCollector<double>::Enabled(enabled),
delimiter
))
, _filename(std::move(filename))
, _delimiter(std::move(delimiter))
, _dumpEveryXRecord(dumpEveryXRecord)
{
}
StatsCollector::~StatsCollector() {
dumpToDisk();
}
void StatsCollector::startNewRecord() {
ghoul_assert(i.enabled() == d.enabled(), "Both Statscollector have to be synced");
if (i.enabled()) {
if (_dumpEveryXRecord && (++_recordsSinceLastDump >= _dumpEveryXRecord)) {
dumpToDisk();
_recordsSinceLastDump = 0;
}
i.startNewRecord();
d.startNewRecord();
}
}
void StatsCollector::setEnabled(bool enabled) {
i.setEnabled(enabled);
d.setEnabled(enabled);
}
int StatsCollector::hasHeaders() {
return i.hasHeaders() || d.hasHeaders();
}
void StatsCollector::dumpToDisk() {
ghoul_assert(i.enabled() == d.enabled(), "Both Statscollector have to be synced");
if (i.enabled() && hasHeaders()) {
if (!_hasWrittenHeader) {
writeHeader();
}
writeData();
}
}
void StatsCollector::writeHeader() {
std::ofstream ofs(_filename);
if (i.hasHeaders()) {
i.writeHeader(ofs);
if (d.hasHeaders()) {
ofs << _delimiter;
d.writeHeader(ofs);
}
}
else {
d.writeHeader(ofs);
}
_hasWrittenHeader = true;
ofs << std::endl;
ofs.close();
}
void StatsCollector::writeData() {
std::ofstream ofs(_filename, std::ofstream::out | std::ofstream::app);
ofs << std::setprecision(32);
while (i.hasRecordsToWrite() || d.hasRecordsToWrite()) {
if (i.hasHeaders() && d.hasHeaders()) {
i.writeNextRecord(ofs); ofs << _delimiter; d.writeNextRecord(ofs);
}
else {
i.writeNextRecord(ofs); d.writeNextRecord(ofs);
}
ofs << std::endl;
}
i.reset();
d.reset();
ofs.close();
}
} // namespace openspace::globebrowsing

View File

@@ -1,73 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___STATS_COLLECTOR___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___STATS_COLLECTOR___H__
#include <modules/globebrowsing/other/templatedstatscollector.h>
#include <ghoul/misc/boolean.h>
#include <string>
namespace openspace::globebrowsing {
class StatsCollector {
public:
BooleanType(Enabled);
StatsCollector() = delete;
StatsCollector(std::string filename, int dumpEveryXRecord,
Enabled enabled = Enabled::Yes, std::string delimiter = ",");
~StatsCollector();
void startNewRecord();
void setEnabled(bool enabled);
int hasHeaders();
void dumpToDisk();
TemplatedStatsCollector<long long> i;
TemplatedStatsCollector<double> d;
private:
void writeHeader();
void writeData();
std::string _filename;
std::string _delimiter;
int _dumpEveryXRecord;
int _recordsSinceLastDump = 0;
bool _hasWrittenHeader = false;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___STATS_COLLECTOR___H__

View File

@@ -1,81 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___TEMPLATED_STATS_COLLECTOR___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TEMPLATED_STATS_COLLECTOR___H__
#include <ghoul/misc/boolean.h>
#include <set>
#include <string>
#include <unordered_map>
#include <vector>
namespace openspace::globebrowsing {
template <typename T>
class TemplatedStatsCollector {
public:
BooleanType(Enabled);
TemplatedStatsCollector(Enabled enabled, std::string delimiter);
~TemplatedStatsCollector() = default;
void startNewRecord();
T& operator[](const std::string& name);
T previous(const std::string& name) const;
void setEnabled(bool enabled);
bool enabled() const;
bool hasHeaders() const;
bool hasRecordsToWrite() const;
void reset();
void writeHeader(std::ostream& os);
void writeNextRecord(std::ostream& os);
private:
template <typename U>
using StatsRecord = std::unordered_map<std::string, U>;
template <typename U>
struct StatsCollection : public std::vector<StatsRecord<U>> {
std::set<std::string> keys;
};
StatsCollection<T> _data;
T _dummy; // used when disabled
bool _enabled;
size_t _writePos = 0;
std::string _delimiter;
};
} // namespace openspace::globebrowsing
#include "templatedstatscollector.inl"
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TEMPLATED_STATS_COLLECTOR___H__

View File

@@ -1,118 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
namespace openspace::globebrowsing {
template <typename T>
TemplatedStatsCollector<T>::TemplatedStatsCollector(Enabled enabled,
std::string delimiter)
: _enabled(enabled)
, _delimiter(std::move(delimiter))
{}
template <typename T>
void TemplatedStatsCollector<T>::startNewRecord() {
if (_enabled) {
_data.push_back(StatsRecord<T>());
}
}
template <typename T>
T& TemplatedStatsCollector<T>::operator[](const std::string& name) {
if (_enabled) {
_data.keys.insert(name);
return _data.back()[name];
}
else {
return _dummy;
}
}
template<typename T>
T TemplatedStatsCollector<T>::previous(const std::string& name) const {
if (_data.size() > 1) {
return _data[_data.size() - 2][name];
}
return T();
}
template<typename T>
void TemplatedStatsCollector<T>::setEnabled(bool enabled) {
_enabled = enabled;
}
template<typename T>
bool TemplatedStatsCollector<T>::enabled() const {
return _enabled;
}
template<typename T>
bool TemplatedStatsCollector<T>::hasHeaders() const {
return !_data.keys.empty();
}
template<typename T>
bool TemplatedStatsCollector<T>::hasRecordsToWrite() const {
return _writePos < (_data.size() - 1);
}
template<typename T>
void TemplatedStatsCollector<T>::reset() {
// copy last, i.e. current record
StatsRecord<T> lastRecord = _data.back();
_data.clear();
// add it again after cleared the vector
_data.push_back(std::move(lastRecord));
_writePos = 0;
}
template<typename T>
void TemplatedStatsCollector<T>::writeHeader(std::ostream& os) {
auto keyIt = _data.keys.begin();
os << *keyIt;
while (++keyIt != _data.keys.end()) {
os << _delimiter << *keyIt;
}
}
template<typename T>
void TemplatedStatsCollector<T>::writeNextRecord(std::ostream& os) {
if (hasRecordsToWrite()) {
// output line by line
StatsRecord<T>& record = _data[_writePos];
// Access every key. Records with no entry will get a default value
auto keyIt = _data.keys.begin();
if (keyIt != _data.keys.end()) {
os << record[(*keyIt)];
while (++keyIt != _data.keys.end()) {
os << _delimiter << record[(*keyIt)];
}
}
_writePos++;
}
}
} // namespace openspace::globebrowsing

View File

@@ -1,547 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/rendering/chunkrenderer.h>
#include <modules/globebrowsing/chunk/chunk.h>
#include <modules/globebrowsing/geometry/ellipsoid.h>
#include <modules/globebrowsing/globes/renderableglobe.h>
#include <modules/globebrowsing/meshes/grid.h>
#include <modules/globebrowsing/meshes/trianglesoup.h>
#include <modules/globebrowsing/rendering/layershadermanager.h>
#include <modules/globebrowsing/rendering/layer/layermanager.h>
#include <modules/globebrowsing/rendering/gpu/gpulayergroup.h>
#include <modules/globebrowsing/rendering/gpu/gpulayermanager.h>
#include <modules/globebrowsing/rendering/layer/layergroup.h>
#include <openspace/util/updatestructures.h>
#include <openspace/util/spicemanager.h>
#include <ghoul/opengl/programobject.h>
namespace {
constexpr const double KM_TO_M = 1000.0;
} // namespace
namespace openspace::globebrowsing {
ChunkRenderer::ChunkRenderer(std::shared_ptr<Grid> grid,
std::shared_ptr<LayerManager> layerManager,
Ellipsoid& ellipsoid)
: _grid(std::move(grid))
, _layerManager(std::move(layerManager))
, _ellipsoid(ellipsoid)
{
_globalLayerShaderManager = std::make_shared<LayerShaderManager>(
"GlobalChunkedLodPatch",
"${MODULE_GLOBEBROWSING}/shaders/globalchunkedlodpatch_vs.glsl",
"${MODULE_GLOBEBROWSING}/shaders/globalchunkedlodpatch_fs.glsl"
);
_localLayerShaderManager = std::make_shared<LayerShaderManager>(
"LocalChunkedLodPatch",
"${MODULE_GLOBEBROWSING}/shaders/localchunkedlodpatch_vs.glsl",
"${MODULE_GLOBEBROWSING}/shaders/localchunkedlodpatch_fs.glsl"
);
_globalGpuLayerManager = std::make_shared<GPULayerManager>();
_localGpuLayerManager = std::make_shared<GPULayerManager>();
}
ChunkRenderer::~ChunkRenderer() {} // NOLINT
void ChunkRenderer::renderChunk(const Chunk& chunk, const RenderData& data) {
// A little arbitrary with 10 but it works
if (chunk.tileIndex().level <
chunk.owner().debugProperties().modelSpaceRenderingCutoffLevel)
{
renderChunkGlobally(chunk, data);
}
else {
renderChunkLocally(chunk, data);
}
}
void ChunkRenderer::update() {
// unused atm. Could be used for caching or precalculating
}
void ChunkRenderer::recompileShaders(const RenderableGlobe& globe) {
LayerShaderManager::LayerShaderPreprocessingData preprocessingData =
LayerShaderManager::LayerShaderPreprocessingData::get(globe);
_globalLayerShaderManager->recompileShaderProgram(preprocessingData);
_localLayerShaderManager->recompileShaderProgram(preprocessingData);
}
ghoul::opengl::ProgramObject* ChunkRenderer::getActivatedProgramWithTileData(
LayerShaderManager& layeredShaderManager,
GPULayerManager& gpuLayerManager,
const Chunk& chunk)
{
const TileIndex& tileIndex = chunk.tileIndex();
// Now the shader program can be accessed
ghoul::opengl::ProgramObject* programObject = layeredShaderManager.programObject();
if (layeredShaderManager.updatedSinceLastCall()) {
gpuLayerManager.bind(programObject, *_layerManager);
}
// Activate the shader program
programObject->activate();
gpuLayerManager.setValue(programObject, *_layerManager, tileIndex);
// The length of the skirts is proportional to its size
programObject->setUniform(
"skirtLength",
static_cast<float>(
glm::min(
chunk.surfacePatch().halfSize().lat * 1000000,
_ellipsoid.minimumRadius()
)
)
);
//programObject->setUniform("skirtLength",
// glm::min(static_cast<float>(chunk.surfacePatch().halfSize().lat * 1000000),
// 8700.0f));
programObject->setUniform("xSegments", _grid->xSegments());
if (chunk.owner().debugProperties().showHeightResolution) {
programObject->setUniform(
"vertexResolution",
glm::vec2(_grid->xSegments(), _grid->ySegments())
);
}
return programObject;
}
void ChunkRenderer::calculateEclipseShadows(const Chunk& chunk,
ghoul::opengl::ProgramObject* programObject,
const RenderData& data)
{
// Shadow calculations..
if (chunk.owner().ellipsoid().hasEclipseShadows()) {
std::vector<RenderableGlobe::ShadowRenderingStruct> shadowDataArray;
std::vector<Ellipsoid::ShadowConfiguration> shadowConfArray =
chunk.owner().ellipsoid().shadowConfigurationArray();
shadowDataArray.reserve(shadowConfArray.size());
double lt;
for (const auto & shadowConf : shadowConfArray) {
// TO REMEMBER: all distances and lengths in world coordinates are in
// meters!!! We need to move this to view space...
// Getting source and caster:
glm::dvec3 sourcePos = SpiceManager::ref().targetPosition(
shadowConf.source.first,
"SUN",
"GALACTIC",
{},
data.time.j2000Seconds(),
lt
);
sourcePos *= KM_TO_M; // converting to meters
glm::dvec3 casterPos = SpiceManager::ref().targetPosition(
shadowConf.caster.first,
"SUN",
"GALACTIC",
{},
data.time.j2000Seconds(),
lt
);
casterPos *= KM_TO_M; // converting to meters
// psc caster_pos = PowerScaledCoordinate::CreatePowerScaledCoordinate(
// casterPos.x,
// casterPos.y,
// casterPos.z
// );
// First we determine if the caster is shadowing the current planet (all
// calculations in World Coordinates):
const glm::dvec3 planetCasterVec = casterPos - data.position.dvec3();
const glm::dvec3 sourceCasterVec = casterPos - sourcePos;
const double sc_length = glm::length(sourceCasterVec);
const glm::dvec3 planetCaster_proj =
(glm::dot(planetCasterVec, sourceCasterVec) / (sc_length*sc_length)) *
sourceCasterVec;
const double d_test = glm::length(planetCasterVec - planetCaster_proj);
const double xp_test = shadowConf.caster.second * sc_length /
(shadowConf.source.second + shadowConf.caster.second);
const double rp_test = shadowConf.caster.second *
(glm::length(planetCaster_proj) + xp_test) / xp_test;
const glm::dvec3 sunPos = SpiceManager::ref().targetPosition(
"SUN",
"SUN",
"GALACTIC",
{},
data.time.j2000Seconds(),
lt
);
const double casterDistSun = glm::length(casterPos - sunPos);
const double planetDistSun = glm::length(data.position.dvec3() - sunPos);
RenderableGlobe::ShadowRenderingStruct shadowData;
shadowData.isShadowing = false;
// Eclipse shadows considers planets and moons as spheres
if (((d_test - rp_test) < (chunk.owner().ellipsoid().radii().x * KM_TO_M)) &&
(casterDistSun < planetDistSun))
{
// The current caster is shadowing the current planet
shadowData.isShadowing = true;
shadowData.rs = shadowConf.source.second;
shadowData.rc = shadowConf.caster.second;
shadowData.sourceCasterVec = glm::normalize(sourceCasterVec);
shadowData.xp = xp_test;
shadowData.xu = shadowData.rc * sc_length /
(shadowData.rs - shadowData.rc);
shadowData.casterPositionVec = casterPos;
}
shadowDataArray.push_back(shadowData);
}
const std::string uniformVarName("shadowDataArray[");
unsigned int counter = 0;
for (const RenderableGlobe::ShadowRenderingStruct& sd : shadowDataArray) {
constexpr const char* NameIsShadowing = "shadowDataArray[{}].isShadowing";
constexpr const char* NameXp = "shadowDataArray[{}].xp";
constexpr const char* NameXu = "shadowDataArray[{}].xu";
constexpr const char* NameRc = "shadowDataArray[{}].rc";
constexpr const char* NameSource = "shadowDataArray[{}].sourceCasterVec";
constexpr const char* NamePos= "shadowDataArray[{}].casterPositionVec";
programObject->setUniform(
fmt::format(NameIsShadowing, counter), sd.isShadowing
);
if (sd.isShadowing) {
programObject->setUniform(fmt::format(NameXp, counter), sd.xp);
programObject->setUniform(fmt::format(NameXu, counter), sd.xu);
programObject->setUniform(fmt::format(NameRc, counter), sd.rc);
programObject->setUniform(
fmt::format(NameSource, counter), sd.sourceCasterVec
);
programObject->setUniform(
fmt::format(NamePos, counter), sd.casterPositionVec
);
}
counter++;
}
programObject->setUniform(
"inverseViewTransform",
glm::inverse(data.camera.combinedViewMatrix())
);
programObject->setUniform("modelTransform", chunk.owner().modelTransform());
programObject->setUniform(
"hardShadows",
chunk.owner().generalProperties().eclipseHardShadows
);
programObject->setUniform("calculateEclipseShadows", true);
}
}
void ChunkRenderer::setCommonUniforms(ghoul::opengl::ProgramObject& programObject,
const Chunk& chunk, const RenderData& data)
{
const glm::dmat4 modelTransform = chunk.owner().modelTransform();
const glm::dmat4 viewTransform = data.camera.combinedViewMatrix();
const glm::dmat4 modelViewTransform = viewTransform * modelTransform;
const bool nightLayersActive =
!_layerManager->layerGroup(layergroupid::NightLayers).activeLayers().empty();
const bool waterLayersActive =
!_layerManager->layerGroup(layergroupid::WaterMasks).activeLayers().empty();
if (nightLayersActive || waterLayersActive ||
chunk.owner().generalProperties().atmosphereEnabled ||
chunk.owner().generalProperties().performShading)
{
const glm::dvec3 directionToSunWorldSpace =
length(data.modelTransform.translation) > 0.0 ?
glm::normalize(-data.modelTransform.translation) :
glm::dvec3(0.0);
const glm::vec3 directionToSunCameraSpace = glm::vec3(viewTransform *
glm::dvec4(directionToSunWorldSpace, 0));
programObject.setUniform(
"lightDirectionCameraSpace",
-glm::normalize(directionToSunCameraSpace)
);
}
if (chunk.owner().generalProperties().performShading) {
programObject.setUniform(
"orenNayarRoughness",
chunk.owner().generalProperties().orenNayarRoughness);
}
if (chunk.owner().generalProperties().useAccurateNormals &&
!_layerManager->layerGroup(layergroupid::HeightLayers).activeLayers().empty())
{
const glm::dvec3 corner00 = chunk.owner().ellipsoid().cartesianSurfacePosition(
chunk.surfacePatch().corner(Quad::SOUTH_WEST)
);
const glm::dvec3 corner10 = chunk.owner().ellipsoid().cartesianSurfacePosition(
chunk.surfacePatch().corner(Quad::SOUTH_EAST)
);
const glm::dvec3 corner01 = chunk.owner().ellipsoid().cartesianSurfacePosition(
chunk.surfacePatch().corner(Quad::NORTH_WEST)
);
const glm::dvec3 corner11 = chunk.owner().ellipsoid().cartesianSurfacePosition(
chunk.surfacePatch().corner(Quad::NORTH_EAST)
);
// This is an assumption that the height tile has a resolution of 64 * 64
// If it does not it will still produce "correct" normals. If the resolution is
// higher the shadows will be softer, if it is lower, pixels will be visible.
// Since default is 64 this will most likely work fine.
const glm::mat3& modelViewTransformMat3 = glm::mat3(modelViewTransform);
constexpr const float TileDelta = 1.f / 64.f;
const glm::vec3 deltaTheta0 = modelViewTransformMat3 *
(glm::vec3(corner10 - corner00) * TileDelta);
const glm::vec3 deltaTheta1 = modelViewTransformMat3 *
(glm::vec3(corner11 - corner01) * TileDelta);
const glm::vec3 deltaPhi0 = modelViewTransformMat3 *
(glm::vec3(corner01 - corner00) * TileDelta);
const glm::vec3 deltaPhi1 = modelViewTransformMat3 *
(glm::vec3(corner11 - corner10) * TileDelta);
// Upload uniforms
programObject.setUniform("deltaTheta0", glm::length(deltaTheta0));
programObject.setUniform("deltaTheta1", glm::length(deltaTheta1));
programObject.setUniform("deltaPhi0", glm::length(deltaPhi0));
programObject.setUniform("deltaPhi1", glm::length(deltaPhi1));
programObject.setUniform("tileDelta", TileDelta);
// This should not be needed once the light calculations for the atmosphere
// is performed in view space..
programObject.setUniform(
"invViewModelTransform",
glm::inverse(
glm::mat4(data.camera.combinedViewMatrix()) *
glm::mat4(chunk.owner().modelTransform())
)
);
}
}
void ChunkRenderer::renderChunkGlobally(const Chunk& chunk, const RenderData& data) {
ghoul::opengl::ProgramObject* programObject = getActivatedProgramWithTileData(
*_globalLayerShaderManager,
*_globalGpuLayerManager,
chunk
);
if (!programObject) {
return;
}
const Ellipsoid& ellipsoid = chunk.owner().ellipsoid();
if (_layerManager->hasAnyBlendingLayersEnabled()) {
// Calculations are done in the reference frame of the globe. Hence, the
// camera position needs to be transformed with the inverse model matrix
const glm::dmat4 inverseModelTransform = chunk.owner().inverseModelTransform();
const glm::dvec3 cameraPosition = glm::dvec3(
inverseModelTransform * glm::dvec4(data.camera.positionVec3(), 1.0)
);
const float distanceScaleFactor = static_cast<float>(
chunk.owner().generalProperties().lodScaleFactor * ellipsoid.minimumRadius()
);
programObject->setUniform("cameraPosition", glm::vec3(cameraPosition));
programObject->setUniform("distanceScaleFactor", distanceScaleFactor);
programObject->setUniform("chunkLevel", chunk.tileIndex().level);
}
// Calculate other uniform variables needed for rendering
const Geodetic2 swCorner = chunk.surfacePatch().corner(Quad::SOUTH_WEST);
const Geodetic2& patchSize = chunk.surfacePatch().size();
const glm::dmat4 modelTransform = chunk.owner().modelTransform();
const glm::dmat4 viewTransform = data.camera.combinedViewMatrix();
const glm::mat4 modelViewTransform = glm::mat4(viewTransform * modelTransform);
const glm::mat4 modelViewProjectionTransform =
data.camera.sgctInternal.projectionMatrix() * modelViewTransform;
// Upload the uniform variables
programObject->setUniform(
"modelViewProjectionTransform",
modelViewProjectionTransform
);
programObject->setUniform("minLatLon", glm::vec2(swCorner.toLonLatVec2()));
programObject->setUniform("lonLatScalingFactor", glm::vec2(patchSize.toLonLatVec2()));
// Ellipsoid Radius (Model Space)
programObject->setUniform("radiiSquared", glm::vec3(ellipsoid.radiiSquared()));
const bool hasNightLayers = !_layerManager->layerGroup(
layergroupid::GroupID::NightLayers
).activeLayers().empty();
const bool hasWaterLayer = !_layerManager->layerGroup(
layergroupid::GroupID::WaterMasks
).activeLayers().empty();
const bool hasHeightLayer = !_layerManager->layerGroup(
layergroupid::HeightLayers
).activeLayers().empty();
if (hasNightLayers || hasWaterLayer ||
chunk.owner().generalProperties().atmosphereEnabled ||
chunk.owner().generalProperties().performShading)
{
programObject->setUniform("modelViewTransform", modelViewTransform);
}
if (chunk.owner().generalProperties().useAccurateNormals && hasHeightLayer) {
// Apply an extra scaling to the height if the object is scaled
programObject->setUniform(
"heightScale",
static_cast<float>(data.modelTransform.scale * data.camera.scaling())
);
}
setCommonUniforms(*programObject, chunk, data);
if (chunk.owner().ellipsoid().hasEclipseShadows()) {
calculateEclipseShadows(chunk, programObject, data);
}
// OpenGL rendering settings
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
// render
_grid->geometry().drawUsingActiveProgram();
_globalGpuLayerManager->deactivate();
// disable shader
programObject->deactivate();
}
void ChunkRenderer::renderChunkLocally(const Chunk& chunk, const RenderData& data) {
ghoul::opengl::ProgramObject* programObject = getActivatedProgramWithTileData(
*_localLayerShaderManager,
*_localGpuLayerManager,
chunk
);
if (!programObject) {
return;
}
const Ellipsoid& ellipsoid = chunk.owner().ellipsoid();
if (_layerManager->hasAnyBlendingLayersEnabled()) {
float distanceScaleFactor = static_cast<float>(
chunk.owner().generalProperties().lodScaleFactor *
chunk.owner().ellipsoid().minimumRadius()
);
programObject->setUniform("distanceScaleFactor", distanceScaleFactor);
programObject->setUniform("chunkLevel", chunk.tileIndex().level);
}
// Calculate other uniform variables needed for rendering
// Send the matrix inverse to the fragment for the global and local shader (JCC)
const glm::dmat4 modelTransform = chunk.owner().modelTransform();
const glm::dmat4 viewTransform = data.camera.combinedViewMatrix();
const glm::dmat4 modelViewTransform = viewTransform * modelTransform;
std::array<glm::dvec3, 4> cornersCameraSpace;
std::array<glm::dvec3, 4> cornersModelSpace;
for (int i = 0; i < 4; ++i) {
constexpr const std::array<const char*, 4> CornerNames = {
"p01", "p11", "p00", "p10"
};
const Quad q = static_cast<Quad>(i);
const Geodetic2 corner = chunk.surfacePatch().corner(q);
const glm::dvec3 cornerModelSpace = ellipsoid.cartesianSurfacePosition(corner);
cornersModelSpace[i] = cornerModelSpace;
const glm::dvec3 cornerCameraSpace = glm::dvec3(
modelViewTransform * glm::dvec4(cornerModelSpace, 1)
);
cornersCameraSpace[i] = cornerCameraSpace;
programObject->setUniform(CornerNames[i], glm::vec3(cornerCameraSpace));
}
// TODO: Patch normal can be calculated for all corners and then linearly
// interpolated on the GPU to avoid cracks for high altitudes.
const glm::vec3 patchNormalCameraSpace = normalize(
cross(
cornersCameraSpace[Quad::SOUTH_EAST] - cornersCameraSpace[Quad::SOUTH_WEST],
cornersCameraSpace[Quad::NORTH_EAST] - cornersCameraSpace[Quad::SOUTH_WEST]
)
);
// In order to improve performance, lets use the normal in object space (model space)
// for deferred rendering.
const glm::vec3 patchNormalModelSpace = normalize(
cross(
cornersModelSpace[Quad::SOUTH_EAST] - cornersModelSpace[Quad::SOUTH_WEST],
cornersModelSpace[Quad::NORTH_EAST] - cornersModelSpace[Quad::SOUTH_WEST]
)
);
programObject->setUniform("patchNormalModelSpace", patchNormalModelSpace);
programObject->setUniform("patchNormalCameraSpace", patchNormalCameraSpace);
programObject->setUniform(
"projectionTransform",
data.camera.sgctInternal.projectionMatrix()
);
if (!_layerManager->layerGroup(layergroupid::HeightLayers).activeLayers().empty()) {
// Apply an extra scaling to the height if the object is scaled
programObject->setUniform(
"heightScale",
static_cast<float>(data.modelTransform.scale * data.camera.scaling())
);
}
setCommonUniforms(*programObject, chunk, data);
if (chunk.owner().ellipsoid().hasEclipseShadows()) {
calculateEclipseShadows(chunk, programObject, data);
}
// OpenGL rendering settings
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
// render
_grid->geometry().drawUsingActiveProgram();
_localGpuLayerManager->deactivate();
// disable shader
programObject->deactivate();
}
} // namespace openspace:;globebrowsing

View File

@@ -1,111 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___CHUNK_RENDERER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___CHUNK_RENDERER___H__
#include <memory>
namespace ghoul::opengl { class ProgramObject; }
namespace openspace { struct RenderData; }
namespace openspace::globebrowsing {
class Chunk;
class Ellipsoid;
class Grid;
class GPULayerManager;
class LayerManager;
class LayerShaderManager;
class RenderableGlobe;
class ChunkRenderer {
public:
ChunkRenderer(std::shared_ptr<Grid> grid, std::shared_ptr<LayerManager> layerManager,
Ellipsoid& ellipsoid);
~ChunkRenderer();
/**
* Chooses to render a chunk either locally or globally depending on the chunklevel
* of the <code>Chunk</code>.
*/
void renderChunk(const Chunk& chunk, const RenderData& data);
void update();
void recompileShaders(const RenderableGlobe& globe);
private:
/**
* Chunks can be rendered either globally or locally. Global rendering is performed
* in the model space of the globe. With global rendering, the vertex positions
* of a chunk are calculated in the vertex shader by transforming the geodetic
* coordinates of the chunk to model space coordinates. We can only achieve floating
* point precision by doing this which means that the camera too close to a global
* tile will lead to jagging. We only render global chunks for lower chunk levels.
*/
void renderChunkGlobally(const Chunk& chunk, const RenderData& data);
/**
* Local rendering of chunks are done using linear interpolation in camera space.
* All four corner points of the chunk are calculated in double precision on the
* CPU and transformed to camera space with double precision matrix transforms.
* These positions can then be cast to floats and uploaded to the vertex shader.
* The vertex shader rendering performs linear interpolation between the four
* corner points to get the resulting chunk. This means that there will be an error
* due to the curvature of the globe. The smaller the patch is (with higher chunk
* levels) the better the approximation becomes. This is why we only render local
* chunks for higher chunk levels.
*/
void renderChunkLocally(const Chunk& chunk, const RenderData& data);
ghoul::opengl::ProgramObject* getActivatedProgramWithTileData(
LayerShaderManager& layeredShaderManager, GPULayerManager& gpuLayerManager,
const Chunk& chunk);
void calculateEclipseShadows(const Chunk& chunk,
ghoul::opengl::ProgramObject* programObject, const RenderData& data);
void setCommonUniforms(ghoul::opengl::ProgramObject& programObject,
const Chunk& chunk, const RenderData& data);
// shared pointer to a grid which can be the same for all rendered chunks.
std::shared_ptr<Grid> _grid;
std::shared_ptr<LayerManager> _layerManager;
Ellipsoid& _ellipsoid;
// Two different shader programs. One for global and one for local rendering.
std::shared_ptr<LayerShaderManager> _globalLayerShaderManager;
std::shared_ptr<LayerShaderManager> _localLayerShaderManager;
// Layered texture uniforms are chached in the uniform ID handles.
std::shared_ptr<GPULayerManager> _globalGpuLayerManager;
std::shared_ptr<GPULayerManager> _localGpuLayerManager;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___CHUNK_RENDERER___H__

View File

@@ -1,50 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/rendering/gpu/gpuchunktile.h>
#include <modules/globebrowsing/tile/chunktile.h>
#include <modules/globebrowsing/tile/tile.h>
namespace openspace::globebrowsing {
void GPUChunkTile::setValue(ghoul::opengl::ProgramObject* programObject,
const ChunkTile& chunkTile)
{
gpuTexture.setValue(programObject, chunkTile.tile.texture());
gpuTileUvTransform.setValue(programObject, chunkTile.uvTransform);
}
void GPUChunkTile::bind(ghoul::opengl::ProgramObject* programObject,
const std::string& nameBase)
{
gpuTexture.bind(programObject, nameBase + "textureSampler");
gpuTileUvTransform.bind(programObject, nameBase + "uvTransform.");
}
void GPUChunkTile::deactivate() {
gpuTexture.deactivate();
}
} // namespace openspace::globebrowsing

View File

@@ -1,73 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___GPUCHUNKTILE___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___GPUCHUNKTILE___H__
#include <modules/globebrowsing/rendering/gpu/gputileuvtransform.h>
#include <openspace/util/gpudata.h>
#include <string>
namespace ghoul::opengl { class ProgramObject; }
namespace openspace::globebrowsing {
struct ChunkTile;
/**
* Manages a GPU representation of a <code>ChunkTile</code>
*/
class GPUChunkTile {
public:
/**
* Sets the value of <code>ChunkTile</code> to its corresponding
* GPU struct. OBS! Users must ensure bind has been
* called before setting using this method.
*/
void setValue(ghoul::opengl::ProgramObject* programObject,
const ChunkTile& chunkTile);
/**
* Binds GLSL variables with identifiers starting with
* nameBase within the provided shader program with this object.
* After this method has been called, users may invoke setValue.
*/
void bind(ghoul::opengl::ProgramObject* programObject, const std::string& nameBase);
/**
* Deactivates any <code>TextureUnit</code>s assigned by this object.
* This method should be called after the OpenGL draw call.
*/
void deactivate();
private:
GPUTexture gpuTexture;
GPUTileUvTransform gpuTileUvTransform;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___GPUCHUNKTILE___H__

View File

@@ -1,59 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/rendering/gpu/gpuchunktilepile.h>
#include <openspace/util/gpudata.h>
namespace openspace::globebrowsing {
void GPUChunkTilePile::setValue(ghoul::opengl::ProgramObject* programObject,
const ChunkTilePile& chunkTilePile)
{
ghoul_assert(
_gpuChunkTiles.size() == chunkTilePile.size(),
"GPU and CPU ChunkTilePile must have same size!"
);
for (size_t i = 0; i < _gpuChunkTiles.size(); ++i) {
_gpuChunkTiles[i].setValue(programObject, chunkTilePile[i]);
}
}
void GPUChunkTilePile::bind(ghoul::opengl::ProgramObject* programObject,
const std::string& nameBase, int pileSize)
{
_gpuChunkTiles.resize(pileSize);
for (size_t i = 0; i < _gpuChunkTiles.size(); ++i) {
std::string nameExtension = "chunkTile" + std::to_string(i) + ".";
_gpuChunkTiles[i].bind(programObject, nameBase + nameExtension);
}
}
void GPUChunkTilePile::deactivate() {
for (GPUChunkTile& t : _gpuChunkTiles) {
t.deactivate();
}
}
} // namespace openspace::globebrowsing

View File

@@ -1,69 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___GPUCHUNKTILEPILE___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___GPUCHUNKTILEPILE___H__
#include <modules/globebrowsing/rendering/gpu/gpuchunktile.h>
#include <modules/globebrowsing/tile/chunktile.h>
#include <string>
#include <vector>
namespace ghoul::opengl { class ProgramObject; }
namespace openspace::globebrowsing {
/**
* Manages a GPU representation of a <code>ChunkTilePile</code>
*/
class GPUChunkTilePile {
public:
/**
* Sets the value of <code>ChunkTilePile</code> to its corresponding
* GPU struct. OBS! Users must ensure bind has been
* called before setting using this method.
*/
void setValue(ghoul::opengl::ProgramObject* programObject,
const ChunkTilePile& chunkTilePile);
/**
* Binds this object with GLSL variables with identifiers starting
* with nameBase within the provided shader program.
* After this method has been called, users may invoke setValue.
*/
void bind(ghoul::opengl::ProgramObject* programObject, const std::string& nameBase,
int pileSize);
/**
* Deactivates any <code>TextureUnit</code>s assigned by this object.
* This method should be called after the OpenGL draw call.
*/
void deactivate();
private:
std::vector<GPUChunkTile> _gpuChunkTiles;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___GPUCHUNKTILEPILE___H__

View File

@@ -1,47 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/rendering/gpu/gpuheightlayer.h>
#include <modules/globebrowsing/rendering/layer/layer.h>
namespace openspace::globebrowsing {
void GPUHeightLayer::setValue(ghoul::opengl::ProgramObject* programObject,
const Layer& layer, const TileIndex& tileIndex,
int pileSize)
{
GPULayer::setValue(programObject, layer, tileIndex, pileSize);
_gpuDepthTransform.setValue(programObject, layer.depthTransform());
}
void GPUHeightLayer::bind(ghoul::opengl::ProgramObject* programObject, const Layer& layer,
const std::string& nameBase, int pileSize)
{
GPULayer::bind(programObject, layer, nameBase, pileSize);
_gpuDepthTransform.bind(programObject, nameBase + "depthTransform.");
}
} // namespace openspace::globebrowsing

View File

@@ -1,70 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___GPUHEIGHTLAYER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___GPUHEIGHTLAYER___H__
#include <modules/globebrowsing/rendering/gpu/gpulayer.h>
#include <modules/globebrowsing/rendering/gpu/gputiledepthtransform.h>
#include <string>
namespace ghoul::opengl { class ProgramObject; }
namespace openspace::globebrowsing {
class Layer;
struct TileIndex;
/**
* Manages a GPU representation of a <code>Layer</code> representing
* a height map.
*/
class GPUHeightLayer : public GPULayer {
public:
virtual ~GPUHeightLayer() override = default;
/**
* Sets the value of <code>Layer</code> to its corresponding
* GPU struct. OBS! Users must ensure bind has been
* called before setting using this method.
*/
virtual void setValue(ghoul::opengl::ProgramObject* programObject, const Layer& layer,
const TileIndex& tileIndex, int pileSize) override;
/**
* Binds this object with GLSL variables with identifiers starting
* with nameBase within the provided shader program.
* After this method has been called, users may invoke setValue.
*/
virtual void bind(ghoul::opengl::ProgramObject* programObject, const Layer& layer,
const std::string& nameBase, int pileSize) override;
private:
GPUTileDepthTransform _gpuDepthTransform;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___GPUHEIGHTLAYER___H__

View File

@@ -1,102 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/rendering/gpu/gpulayer.h>
#include <modules/globebrowsing/rendering/layer/layer.h>
namespace openspace::globebrowsing {
void GPULayer::setValue(ghoul::opengl::ProgramObject* programObject, const Layer& layer,
const TileIndex& tileIndex, int pileSize)
{
gpuRenderSettings.setValue(programObject, layer.renderSettings());
gpuLayerAdjustment.setValue(programObject, layer.layerAdjustment());
switch (layer.type()) {
// Intentional fall through. Same for all tile layers
case layergroupid::TypeID::DefaultTileLayer:
case layergroupid::TypeID::SingleImageTileLayer:
case layergroupid::TypeID::SizeReferenceTileLayer:
case layergroupid::TypeID::TemporalTileLayer:
case layergroupid::TypeID::TileIndexTileLayer:
case layergroupid::TypeID::ByIndexTileLayer:
case layergroupid::TypeID::ByLevelTileLayer: {
ChunkTilePile chunkTilePile = layer.chunkTilePile(tileIndex, pileSize);
gpuChunkTilePile.setValue(programObject, chunkTilePile);
paddingStartOffset.setValue(programObject, layer.tilePixelStartOffset());
paddingSizeDifference.setValue(
programObject,
layer.tilePixelSizeDifference()
);
break;
}
case layergroupid::TypeID::SolidColor:
gpuColor.setValue(programObject, layer.otherTypesProperties().color.value());
break;
default:
break;
}
}
void GPULayer::bind(ghoul::opengl::ProgramObject* programObject, const Layer& layer,
const std::string& nameBase, int pileSize)
{
gpuRenderSettings.bind(layer.renderSettings(), programObject, nameBase + "settings.");
gpuLayerAdjustment.bind(
layer.layerAdjustment(),
programObject,
nameBase + "adjustment."
);
switch (layer.type()) {
// Intentional fall through. Same for all tile layers
case layergroupid::TypeID::DefaultTileLayer:
case layergroupid::TypeID::SingleImageTileLayer:
case layergroupid::TypeID::SizeReferenceTileLayer:
case layergroupid::TypeID::TemporalTileLayer:
case layergroupid::TypeID::TileIndexTileLayer:
case layergroupid::TypeID::ByIndexTileLayer:
case layergroupid::TypeID::ByLevelTileLayer: {
gpuChunkTilePile.bind(programObject, nameBase + "pile.", pileSize);
paddingStartOffset.bind(programObject, nameBase + "padding.startOffset");
paddingSizeDifference.bind(
programObject,
nameBase + "padding.sizeDifference"
);
break;
}
case layergroupid::TypeID::SolidColor:
gpuColor.bind(programObject, nameBase + "color");
break;
default:
break;
}
}
void GPULayer::deactivate() {
gpuChunkTilePile.deactivate();
}
} // namespace openspace::globebrowsing

View File

@@ -1,83 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___GPULAYER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___GPULAYER___H__
#include <modules/globebrowsing/rendering/gpu/gpuchunktilepile.h>
#include <modules/globebrowsing/rendering/gpu/gpulayeradjustment.h>
#include <modules/globebrowsing/rendering/gpu/gpulayerrendersettings.h>
#include <openspace/util/gpudata.h>
#include <string>
namespace ghoul::opengl { class ProgramObject; }
namespace openspace::globebrowsing {
class Layer;
struct TileIndex;
/**
* Manages a GPU representation of a <code>Layer</code>
*/
class GPULayer {
public:
virtual ~GPULayer() = default;
/**
* Sets the value of <code>Layer</code> to its corresponding
* GPU struct. OBS! Users must ensure bind has been
* called before setting using this method.
*/
virtual void setValue(ghoul::opengl::ProgramObject* programObject, const Layer& layer,
const TileIndex& tileIndex, int pileSize);
/**
* Binds this object with GLSL variables with identifiers starting
* with nameBase within the provided shader program.
* After this method has been called, users may invoke setValue.
*/
virtual void bind(ghoul::opengl::ProgramObject* programObject, const Layer& layer,
const std::string& nameBase, int pileSize);
/**
* Deactivates any <code>TextureUnit</code>s assigned by this object.
* This method should be called after the OpenGL draw call.
*/
virtual void deactivate();
private:
GPUChunkTilePile gpuChunkTilePile;
GPULayerRenderSettings gpuRenderSettings;
GPULayerAdjustment gpuLayerAdjustment;
GPUData<glm::ivec2> paddingStartOffset;
GPUData<glm::ivec2> paddingSizeDifference;
// Adjustment layer stuff
GPUData<glm::vec3> gpuColor;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___GPULAYER___H__

View File

@@ -1,70 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/rendering/gpu/gpulayeradjustment.h>
#include <modules/globebrowsing/rendering/layer/layeradjustment.h>
namespace openspace::globebrowsing {
void GPULayerAdjustment::setValue(ghoul::opengl::ProgramObject* programObject,
const LayerAdjustment& layerAdjustment)
{
switch (layerAdjustment.type()) {
case layergroupid::AdjustmentTypeID::None:
break;
case layergroupid::AdjustmentTypeID::ChromaKey: {
gpuChromaKeyColor.setValue(
programObject,
layerAdjustment.chromaKeyColor()
);
gpuChromaKeyTolerance.setValue(
programObject,
layerAdjustment.chromaKeyTolerance()
);
break;
}
case layergroupid::AdjustmentTypeID::TransferFunction:
break;
}
}
void GPULayerAdjustment::bind(const LayerAdjustment& layerAdjustment,
ghoul::opengl::ProgramObject* programObject,
const std::string& nameBase)
{
switch (layerAdjustment.type()) {
case layergroupid::AdjustmentTypeID::None:
break;
case layergroupid::AdjustmentTypeID::ChromaKey: {
gpuChromaKeyColor.bind(programObject, nameBase + "chromaKeyColor");
gpuChromaKeyTolerance.bind(programObject, nameBase + "chromaKeyTolerance");
break;
}
case layergroupid::AdjustmentTypeID::TransferFunction:
break;
}
}
} // namespace openspace::globebrowsing

View File

@@ -1,51 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___GPULAYER_ADJUSTMENT___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___GPULAYER_ADJUSTMENT___H__
#include <openspace/util/gpudata.h>
namespace ghoul::opengl { class ProgramObject; }
namespace openspace::globebrowsing {
class LayerAdjustment;
class GPULayerAdjustment{
public:
void setValue(ghoul::opengl::ProgramObject* programObject,
const LayerAdjustment& layerAdjustment);
void bind(const LayerAdjustment& layerAdjustment,
ghoul::opengl::ProgramObject* programObject, const std::string& nameBase);
private:
GPUData<glm::vec3> gpuChromaKeyColor;
GPUData<float> gpuChromaKeyTolerance;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___GPULAYER_ADJUSTMENT___H__

View File

@@ -1,81 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/rendering/gpu/gpulayergroup.h>
#include <modules/globebrowsing/rendering/layer/layergroup.h>
#include <modules/globebrowsing/rendering/layer/layermanager.h>
#include <modules/globebrowsing/rendering/gpu/gpuheightlayer.h>
#include <modules/globebrowsing/rendering/gpu/gpulayer.h>
namespace openspace::globebrowsing {
GPULayerGroup::~GPULayerGroup() {} // NOLINT
void GPULayerGroup::setValue(ghoul::opengl::ProgramObject* programObject,
const LayerGroup& layerGroup, const TileIndex& tileIndex)
{
auto& activeLayers = layerGroup.activeLayers();
ghoul_assert(
activeLayers.size() == _gpuActiveLayers.size(),
"GPU and CPU active layers must have same size!"
);
for (unsigned int i = 0; i < activeLayers.size(); ++i) {
_gpuActiveLayers[i]->setValue(
programObject,
*activeLayers[i],
tileIndex,
layerGroup.pileSize()
);
}
}
void GPULayerGroup::bind(ghoul::opengl::ProgramObject* programObject,
const LayerGroup& layerGroup, const std::string& nameBase,
int category)
{
const std::vector<std::shared_ptr<Layer>>& activeLayers = layerGroup.activeLayers();
_gpuActiveLayers.resize(activeLayers.size());
const int pileSize = layerGroup.pileSize();
for (size_t i = 0; i < _gpuActiveLayers.size(); ++i) {
// should maybe a proper GPULayer factory
_gpuActiveLayers[i] = (category == layergroupid::GroupID::HeightLayers) ?
std::make_unique<GPUHeightLayer>() :
std::make_unique<GPULayer>();
_gpuActiveLayers[i]->bind(
programObject,
*activeLayers[i],
nameBase + "[" + std::to_string(i) + "].",
pileSize
);
}
}
void GPULayerGroup::deactivate() {
for (std::unique_ptr<GPULayer>& l : _gpuActiveLayers) {
l->deactivate();
}
}
} // namespace openspace::globebrowsing

View File

@@ -1,73 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/rendering/gpu/gpulayermanager.h>
#include <modules/globebrowsing/rendering/layer/layermanager.h>
#include <modules/globebrowsing/rendering/gpu/gpulayer.h>
#include <modules/globebrowsing/rendering/gpu/gpulayergroup.h>
namespace openspace::globebrowsing {
GPULayerManager::~GPULayerManager() {} // NOLINT
void GPULayerManager::setValue(ghoul::opengl::ProgramObject* programObject,
const LayerManager& manager, const TileIndex& tileIndex)
{
const std::vector<std::shared_ptr<LayerGroup>>& layerGroups = manager.layerGroups();
for (size_t i = 0; i < layerGroups.size(); ++i) {
_gpuLayerGroups[i]->setValue(programObject, *layerGroups[i], tileIndex);
}
}
void GPULayerManager::bind(ghoul::opengl::ProgramObject* programObject,
const LayerManager& manager)
{
const std::vector<std::shared_ptr<LayerGroup>>& layerGroups = manager.layerGroups();
if (_gpuLayerGroups.size() != layerGroups.size()) {
_gpuLayerGroups.resize(layerGroups.size());
for (std::unique_ptr<GPULayerGroup>& gpuLayerGroup : _gpuLayerGroups) {
gpuLayerGroup = std::make_unique<GPULayerGroup>();
}
}
for (size_t i = 0; i < layerGroups.size(); ++i) {
const std::string& nameBase = layergroupid::LAYER_GROUP_IDENTIFIERS[i];
_gpuLayerGroups[i]->bind(
programObject,
*layerGroups[i],
nameBase,
static_cast<int>(i)
);
}
}
void GPULayerManager::deactivate() {
for (std::unique_ptr<GPULayerGroup>& l : _gpuLayerGroups) {
l->deactivate();
}
}
} // namespace openspace::globebrowsing

View File

@@ -1,75 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___GPULAYERMANAGER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___GPULAYERMANAGER___H__
#include <memory>
#include <string>
#include <vector>
namespace ghoul::opengl { class ProgramObject; }
namespace openspace::globebrowsing {
class GPULayerGroup;
class LayerManager;
struct TileIndex;
/**
* Manages a GPU representation of a <code>LayerGroup</code>
*/
class GPULayerManager {
public:
~GPULayerManager();
/**
* Sets the value of <code>LayerGroup</code> to its corresponding
* GPU struct. OBS! Users must ensure bind has been
* called before setting using this method.
*/
void setValue(ghoul::opengl::ProgramObject* programObject,
const LayerManager& manager, const TileIndex& tileIndex);
/**
* Binds this object with GLSL variables with identifiers starting
* with nameBase within the provided shader program.
* After this method has been called, users may invoke setValue.
*/
void bind(ghoul::opengl::ProgramObject* programObject,
const LayerManager& manager);
/**
* Deactivates any <code>TextureUnit</code>s assigned by this object.
* This method should be called after the OpenGL draw call.
*/
void deactivate();
private:
std::vector<std::unique_ptr<GPULayerGroup>> _gpuLayerGroups;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___GPULAYERMANAGER___H__

View File

@@ -1,50 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/rendering/gpu/gpulayerrendersettings.h>
#include <modules/globebrowsing/rendering/layer/layerrendersettings.h>
namespace openspace::globebrowsing {
void GPULayerRenderSettings::setValue(ghoul::opengl::ProgramObject* programObject,
const LayerRenderSettings& layerSettings)
{
gpuOpacity.setValue(programObject, layerSettings.opacity.value());
gpuGamma.setValue(programObject, layerSettings.gamma.value());
gpuMultiplier.setValue(programObject, layerSettings.multiplier.value());
gpuOffset.setValue(programObject, layerSettings.offset.value());
}
void GPULayerRenderSettings::bind(const LayerRenderSettings&,
ghoul::opengl::ProgramObject* programObject,
const std::string& nameBase)
{
gpuOpacity.bind(programObject, nameBase + "opacity");
gpuGamma.bind(programObject, nameBase + "gamma");
gpuMultiplier.bind(programObject, nameBase + "multiplier");
gpuOffset.bind(programObject, nameBase + "offset");
}
} // namespace openspace::globebrowsing

View File

@@ -1,70 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___GPULAYERRENDERSETTINGS___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___GPULAYERRENDERSETTINGS___H__
#include <openspace/util/gpudata.h>
#include <string>
namespace ghoul::opengl { class ProgramObject; }
namespace openspace::globebrowsing {
struct LayerRenderSettings;
/**
* Manages a GPU representation of a <code>LayerRenderSettings</code>
*/
class GPULayerRenderSettings{
public:
/**
* Sets the value of <code>LayerRenderSettings</code> to its corresponding
* GPU struct. OBS! Users must ensure bind has been
* called before setting using this method.
*/
void setValue(ghoul::opengl::ProgramObject* programObject,
const LayerRenderSettings& layerSettings);
/**
* Binds this object with GLSL variables with identifiers starting
* with nameBase within the provided shader program.
* After this method has been called, users may invoke setValue.
*/
void bind(const LayerRenderSettings& layerSettings,
ghoul::opengl::ProgramObject* programObject, const std::string& nameBase);
private:
GPUData<float> gpuOpacity;
GPUData<float> gpuGamma;
GPUData<float> gpuMultiplier;
GPUData<float> gpuOffset;
// Optional
GPUData<float> gpuValueBlending;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___GPULAYERRENDERSETTINGS___H__

View File

@@ -1,45 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/rendering/gpu/gputiledepthtransform.h>
#include <modules/globebrowsing/tile/tiledepthtransform.h>
namespace openspace::globebrowsing {
void GPUTileDepthTransform::setValue(ghoul::opengl::ProgramObject* programObject,
const TileDepthTransform& depthTransform)
{
_gpuDepthOffset.setValue(programObject, depthTransform.depthOffset);
_gpuDepthScale.setValue(programObject, depthTransform.depthScale);
}
void GPUTileDepthTransform::bind(ghoul::opengl::ProgramObject* programObject,
const std::string& nameBase)
{
_gpuDepthOffset.bind(programObject, nameBase + "depthOffset");
_gpuDepthScale.bind(programObject, nameBase + "depthScale");
}
} // namespace openspace::globebrowsing

View File

@@ -1,65 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___GPUTILEDEPTHTRANSFORM___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___GPUTILEDEPTHTRANSFORM___H__
#include <openspace/util/gpudata.h>
#include <string>
namespace ghoul::opengl { class ProgramObject; }
namespace openspace::globebrowsing {
struct TileDepthTransform;
/**
* Manages a GPU representation of a <code>TileDepthTransform</code>
*/
class GPUTileDepthTransform {
public:
/**
* Sets the value of <code>TileDepthTransform</code> to its corresponding
* GPU struct. OBS! Users must ensure bind has been
* called before setting using this method.
*/
void setValue(ghoul::opengl::ProgramObject* programObject,
const TileDepthTransform& depthTransform);
/**
* Binds GLSL variables with identifiers starting with
* nameBase within the provided shader program with this object.
* After this method has been called, users may invoke setValue.
*/
void bind(ghoul::opengl::ProgramObject* programObject,
const std::string& nameBase);
private:
GPUData<float> _gpuDepthOffset;
GPUData<float> _gpuDepthScale;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___GPUTILEDEPTHTRANSFORM___H__

View File

@@ -1,46 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/rendering/gpu/gputileuvtransform.h>
#include <modules/globebrowsing/tile/tileprovider/tileprovider.h>
#include <modules/globebrowsing/tile/tileuvtransform.h>
namespace openspace::globebrowsing {
void GPUTileUvTransform::setValue(ghoul::opengl::ProgramObject* programObject,
const TileUvTransform& uvTransform)
{
_gpuUvOffset.setValue(programObject, uvTransform.uvOffset);
_gpuUvScale.setValue(programObject, uvTransform.uvScale);
}
void GPUTileUvTransform::bind(ghoul::opengl::ProgramObject* programObject,
const std::string& nameBase)
{
_gpuUvOffset.bind(programObject, nameBase + "uvOffset");
_gpuUvScale.bind(programObject, nameBase + "uvScale");
}
} // namespace openspace::globebrowsing

View File

@@ -1,64 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___GPUTILEUVTRANSFORM___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___GPUTILEUVTRANSFORM___H__
#include <openspace/util/gpudata.h>
#include <string>
namespace ghoul::opengl { class ProgramObject; }
namespace openspace::globebrowsing {
struct TileUvTransform;
/**
* Manages a GPU representation of a <code>TileUvTransform</code>
*/
class GPUTileUvTransform {
public:
/**
* Sets the value of <code>TileUvTransform</code> to its corresponding
* GPU struct. OBS! Users must ensure bind has been
* called before setting using this method.
*/
void setValue(ghoul::opengl::ProgramObject* programObject,
const TileUvTransform& uvTransform);
/**
* Binds GLSL variables with identifiers starting with
* nameBase within the provided shader program with this object.
* After this method has been called, users may invoke setValue.
*/
void bind(ghoul::opengl::ProgramObject* programObject, const std::string& nameBase);
private:
GPUData<glm::vec2> _gpuUvOffset;
GPUData<glm::vec2> _gpuUvScale;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___GPUTILEUVTRANSFORM___H__

View File

@@ -1,228 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/rendering/layer/layermanager.h>
#include <modules/globebrowsing/rendering/layer/layer.h>
#include <modules/globebrowsing/rendering/layer/layergroup.h>
#include <modules/globebrowsing/tile/tiletextureinitdata.h>
#include <modules/globebrowsing/tile/tileprovider/tileprovider.h>
#include <ghoul/logging/logmanager.h>
namespace {
constexpr const char* _loggerCat = "LayerManager";
} // namespace
namespace openspace::globebrowsing {
LayerManager::LayerManager(const ghoul::Dictionary& layerGroupsDict)
: properties::PropertyOwner({ "Layers" })
{
// First create empty layer groups in case not all are specified
_layerGroups.resize(layergroupid::NUM_LAYER_GROUPS);
for (size_t i = 0; i < _layerGroups.size(); ++i) {
ghoul::Dictionary emptyDict;
_layerGroups[i] = std::make_shared<LayerGroup>(
static_cast<layergroupid::GroupID>(i), emptyDict
);
}
const std::vector<std::string>& layerGroupNamesInDict = layerGroupsDict.keys();
// Create all the layer groups
for (const std::string& groupName : layerGroupNamesInDict) {
layergroupid::GroupID groupId = layergroupid::getGroupIDFromName(groupName);
if (groupId != layergroupid::GroupID::Unknown) {
ghoul::Dictionary layerGroupDict = layerGroupsDict.value<ghoul::Dictionary>(
groupName
);
_layerGroups[static_cast<int>(groupId)] = std::make_shared<LayerGroup>(
groupId,
layerGroupDict
);
}
else {
LWARNING("Unknown layer group: " + groupName);
}
}
for (const std::shared_ptr<LayerGroup>& layerGroup : _layerGroups) {
addPropertySubOwner(layerGroup.get());
}
}
void LayerManager::initialize() {
for (const std::shared_ptr<LayerGroup>& lg : _layerGroups) {
lg->initialize();
}
}
void LayerManager::deinitialize() {
for (const std::shared_ptr<LayerGroup>& lg : _layerGroups) {
lg->deinitialize();
}
}
std::shared_ptr<Layer> LayerManager::addLayer(layergroupid::GroupID groupId,
const ghoul::Dictionary& layerDict)
{
ghoul_assert(groupId != layergroupid::Unknown, "Layer group ID must be known");
return _layerGroups[groupId]->addLayer(layerDict);
}
void LayerManager::deleteLayer(layergroupid::GroupID groupId,
const std::string& layerName)
{
ghoul_assert(groupId != layergroupid::Unknown, "Layer group ID must be known");
_layerGroups[groupId]->deleteLayer(layerName);
}
const LayerGroup& LayerManager::layerGroup(size_t groupId) {
return *_layerGroups[groupId];
}
const LayerGroup& LayerManager::layerGroup(layergroupid::GroupID groupId) {
return *_layerGroups[groupId];
}
bool LayerManager::hasAnyBlendingLayersEnabled() const {
return std::any_of(
_layerGroups.begin(),
_layerGroups.end(),
[](const std::shared_ptr<LayerGroup>& layerGroup) {
return layerGroup->layerBlendingEnabled() &&
!layerGroup->activeLayers().empty();
}
);
}
const std::vector<std::shared_ptr<LayerGroup>>& LayerManager::layerGroups() const {
return _layerGroups;
}
void LayerManager::update() {
for (std::shared_ptr<LayerGroup>& layerGroup : _layerGroups) {
layerGroup->update();
}
}
void LayerManager::reset(bool includeDisabled) {
for (std::shared_ptr<LayerGroup>& layerGroup : _layerGroups) {
for (const std::shared_ptr<Layer>& layer : layerGroup->layers()) {
if (layer->enabled() || includeDisabled) {
layer->tileProvider()->reset();
}
}
}
}
TileTextureInitData LayerManager::getTileTextureInitData(layergroupid::GroupID id,
PadTiles padTiles,
size_t preferredTileSize)
{
switch (id) {
case layergroupid::GroupID::HeightLayers: {
const size_t tileSize = preferredTileSize ? preferredTileSize : 64;
return TileTextureInitData(
tileSize,
tileSize,
GL_FLOAT,
ghoul::opengl::Texture::Format::Red,
TileTextureInitData::PadTiles(padTiles),
TileTextureInitData::ShouldAllocateDataOnCPU::Yes
);
}
case layergroupid::GroupID::ColorLayers: {
const size_t tileSize = preferredTileSize ? preferredTileSize : 512;
return TileTextureInitData(
tileSize,
tileSize,
GL_UNSIGNED_BYTE,
ghoul::opengl::Texture::Format::BGRA,
TileTextureInitData::PadTiles(padTiles)
);
}
case layergroupid::GroupID::Overlays: {
const size_t tileSize = preferredTileSize ? preferredTileSize : 512;
return TileTextureInitData(
tileSize,
tileSize,
GL_UNSIGNED_BYTE,
ghoul::opengl::Texture::Format::BGRA,
TileTextureInitData::PadTiles(padTiles)
);
}
case layergroupid::GroupID::NightLayers: {
const size_t tileSize = preferredTileSize ? preferredTileSize : 512;
return TileTextureInitData(
tileSize,
tileSize,
GL_UNSIGNED_BYTE,
ghoul::opengl::Texture::Format::BGRA,
TileTextureInitData::PadTiles(padTiles)
);
}
case layergroupid::GroupID::WaterMasks: {
const size_t tileSize = preferredTileSize ? preferredTileSize : 512;
return TileTextureInitData(
tileSize,
tileSize,
GL_UNSIGNED_BYTE,
ghoul::opengl::Texture::Format::BGRA,
TileTextureInitData::PadTiles(padTiles)
);
}
default: {
ghoul_assert(false, "Unknown layer group ID");
const size_t tileSize = preferredTileSize ? preferredTileSize : 512;
return TileTextureInitData(
tileSize,
tileSize,
GL_UNSIGNED_BYTE,
ghoul::opengl::Texture::Format::BGRA,
TileTextureInitData::PadTiles(padTiles)
);
}
}
}
bool LayerManager::shouldPerformPreProcessingOnLayergroup(layergroupid::GroupID id) {
// Only preprocess height layers by default
switch (id) {
case layergroupid::GroupID::HeightLayers: return true;
default: return false;
}
}
void LayerManager::onChange(std::function<void(void)> callback) {
for (std::shared_ptr<LayerGroup>& layerGroup : _layerGroups) {
layerGroup->onChange(callback);
}
}
} // namespace openspace::globebrowsing

View File

@@ -1,256 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <modules/globebrowsing/rendering/layershadermanager.h>
#include <modules/globebrowsing/chunk/chunk.h>
#include <modules/globebrowsing/globes/chunkedlodglobe.h>
#include <modules/globebrowsing/globes/renderableglobe.h>
#include <modules/globebrowsing/rendering/layer/layer.h>
#include <modules/globebrowsing/rendering/layer/layergroup.h>
#include <modules/globebrowsing/rendering/layer/layermanager.h>
#include <openspace/engine/globals.h>
#include <openspace/rendering/renderengine.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/opengl/programobject.h>
namespace openspace::globebrowsing {
bool
LayerShaderManager::LayerShaderPreprocessingData::LayerGroupPreprocessingData::operator==(
const LayerGroupPreprocessingData& other) const
{
return layerType == other.layerType &&
blendMode == other.blendMode &&
layerAdjustmentType == other.layerAdjustmentType &&
lastLayerIdx == other.lastLayerIdx &&
layerBlendingEnabled == other.layerBlendingEnabled;
}
bool LayerShaderManager::LayerShaderPreprocessingData::operator==(
const LayerShaderPreprocessingData& other) const
{
if (layeredTextureInfo.size() != other.layeredTextureInfo.size() ||
keyValuePairs.size() != other.keyValuePairs.size()) {
return false;
}
else {
bool equal = true;
for (size_t i = 0; i < layeredTextureInfo.size(); i++) {
equal &= (layeredTextureInfo[i] == other.layeredTextureInfo[i]);
}
for (size_t i = 0; i < keyValuePairs.size(); i++) {
equal &= (keyValuePairs[i] == other.keyValuePairs[i]);
}
return equal;
}
}
LayerShaderManager::LayerShaderPreprocessingData
LayerShaderManager::LayerShaderPreprocessingData::get(const RenderableGlobe& globe)
{
LayerShaderManager::LayerShaderPreprocessingData preprocessingData;
std::shared_ptr<LayerManager> layerManager = globe.chunkedLodGlobe()->layerManager();
for (size_t i = 0; i < layergroupid::NUM_LAYER_GROUPS; i++) {
LayerShaderManager::LayerShaderPreprocessingData::LayerGroupPreprocessingData
layeredTextureInfo;
const LayerGroup& layerGroup = layerManager->layerGroup(i);
const std::vector<std::shared_ptr<Layer>>& layers = layerGroup.activeLayers();
// This check was implicit before; not sure if it will fire or will be handled
// elsewhere
//ghoul_assert(
// !layerGroup.activeLayers().empty(),
// "If activeLayers is empty the following line will lead to an overflow"
//);
layeredTextureInfo.lastLayerIdx = static_cast<int>(
layerGroup.activeLayers().size() - 1
);
layeredTextureInfo.layerBlendingEnabled = layerGroup.layerBlendingEnabled();
for (const std::shared_ptr<Layer>& layer : layers) {
layeredTextureInfo.layerType.push_back(layer->type());
layeredTextureInfo.blendMode.push_back(layer->blendMode());
layeredTextureInfo.layerAdjustmentType.push_back(
layer->layerAdjustment().type()
);
}
preprocessingData.layeredTextureInfo[i] = layeredTextureInfo;
}
const RenderableGlobe::GeneralProperties& generalProps = globe.generalProperties();
const RenderableGlobe::DebugProperties& debugProps = globe.debugProperties();
std::vector<std::pair<std::string, std::string>>& pairs =
preprocessingData.keyValuePairs;
pairs.emplace_back("useAccurateNormals",
std::to_string(generalProps.useAccurateNormals)
);
pairs.emplace_back("useAtmosphere", std::to_string(generalProps.atmosphereEnabled));
pairs.emplace_back("performShading", std::to_string(generalProps.performShading));
pairs.emplace_back(
"useEclipseShadows",
std::to_string(generalProps.eclipseShadowsEnabled)
);
pairs.emplace_back(
"useEclipseHardShadows",
std::to_string(generalProps.eclipseHardShadows)
);
pairs.emplace_back("showChunkEdges", std::to_string(debugProps.showChunkEdges));
pairs.emplace_back("showHeightResolution",
std::to_string(debugProps.showHeightResolution)
);
pairs.emplace_back("showHeightIntensities",
std::to_string(debugProps.showHeightIntensities)
);
pairs.emplace_back("defaultHeight", std::to_string(Chunk::DefaultHeight));
return preprocessingData;
}
LayerShaderManager::LayerShaderManager(std::string shaderName, std::string vsPath,
std::string fsPath)
: _shaderName(std::move(shaderName))
, _vsPath(std::move(vsPath))
, _fsPath(std::move(fsPath))
{}
LayerShaderManager::~LayerShaderManager() {
if (_programObject) {
global::renderEngine.removeRenderProgram(_programObject.get());
_programObject = nullptr;
}
}
ghoul::opengl::ProgramObject* LayerShaderManager::programObject() const {
ghoul_assert(_programObject, "Program does not exist. Needs to be compiled!");
return _programObject.get();
}
void LayerShaderManager::recompileShaderProgram(
LayerShaderPreprocessingData preprocessingData)
{
_preprocessingData = std::move(preprocessingData);
ghoul::Dictionary shaderDictionary;
// Different layer types can be height layers or color layers for example.
// These are used differently within the shaders.
const std::array<
LayerShaderPreprocessingData::LayerGroupPreprocessingData,
layergroupid::NUM_LAYER_GROUPS
>& textureTypes = _preprocessingData.layeredTextureInfo;
for (size_t i = 0; i < textureTypes.size(); i++) {
// lastLayerIndex must be at least 0 for the shader to compile,
// the layer type is inactivated by setting use to false
const std::string& groupName = layergroupid::LAYER_GROUP_IDENTIFIERS[i];
shaderDictionary.setValue(
"lastLayerIndex" + groupName,
glm::max(textureTypes[i].lastLayerIdx, 0)
);
shaderDictionary.setValue(
"use" + groupName,
textureTypes[i].lastLayerIdx >= 0
);
shaderDictionary.setValue(
"blend" + groupName,
textureTypes[i].layerBlendingEnabled
);
// This is to avoid errors from shader preprocessor
shaderDictionary.setValue(groupName + "0" + "LayerType", 0);
for (int j = 0; j < textureTypes[i].lastLayerIdx + 1; ++j) {
shaderDictionary.setValue(
groupName + std::to_string(j) + "LayerType",
static_cast<int>(textureTypes[i].layerType[j])
);
}
// This is to avoid errors from shader preprocessor
shaderDictionary.setValue(groupName + "0" + "BlendMode", 0);
for (int j = 0; j < textureTypes[i].lastLayerIdx + 1; ++j) {
shaderDictionary.setValue(
groupName + std::to_string(j) + "BlendMode",
static_cast<int>(textureTypes[i].blendMode[j])
);
}
// This is to avoid errors from shader preprocessor
std::string keyLayerAdjustmentType = groupName + "0" + "LayerAdjustmentType";
shaderDictionary.setValue(keyLayerAdjustmentType, 0);
for (int j = 0; j < textureTypes[i].lastLayerIdx + 1; ++j) {
shaderDictionary.setValue(
groupName + std::to_string(j) + "LayerAdjustmentType",
static_cast<int>(textureTypes[i].layerAdjustmentType[j])
);
}
}
ghoul::Dictionary layerGroupNames;
for (int i = 0; i < layergroupid::NUM_LAYER_GROUPS; ++i) {
layerGroupNames.setValue(
std::to_string(i),
layergroupid::LAYER_GROUP_IDENTIFIERS[i]
);
}
shaderDictionary.setValue("layerGroups", layerGroupNames);
// Other settings such as "useAtmosphere"
for (const std::pair<std::string, std::string>& p : _preprocessingData.keyValuePairs)
{
shaderDictionary.setValue(p.first, p.second);
}
// Remove old program
global::renderEngine.removeRenderProgram(_programObject.get());
_programObject = global::renderEngine.buildRenderProgram(
_shaderName,
absPath(_vsPath),
absPath(_fsPath),
shaderDictionary
);
ghoul_assert(_programObject != nullptr, "Failed to initialize programObject!");
using IgnoreError = ghoul::opengl::ProgramObject::ProgramObject::IgnoreError;
_programObject->setIgnoreSubroutineUniformLocationError(IgnoreError::Yes);
_programObject->setIgnoreUniformLocationError(IgnoreError::Yes);
_updatedSinceLastCall = true;
}
bool LayerShaderManager::updatedSinceLastCall() {
const bool updated = _updatedSinceLastCall;
_updatedSinceLastCall = false;
return updated;
}
} // namespace openspace::globebrowsing

View File

@@ -1,103 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___LAYER_SHADER_MANAGER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___LAYER_SHADER_MANAGER___H__
#include <modules/globebrowsing/rendering/layershadermanager.h>
#include <modules/globebrowsing/rendering/layer/layergroupid.h>
#include <array>
#include <memory>
#include <string>
#include <vector>
namespace ghoul::opengl { class ProgramObject; }
namespace openspace::globebrowsing {
class RenderableGlobe;
/**
* This class has ownership of an updated shader program for rendering tiles.
*/
class LayerShaderManager {
public:
/**
* Data needed for shader preprocessing before compiling a layered texture shader
* program.
*
* If a <code>LayerShaderPreprocessingData</code> is compared with another it can
* be determined wheter or not a <code>LayerShaderManager</code> needs to
* recompile its shader program. For each <code>TextureGroup</code> there is
* information about how many layers it has and whether or not to blend the texture
* levels.
*/
struct LayerShaderPreprocessingData {
/**
* Settings per texture group that contains shader preprocessing information.
*/
struct LayerGroupPreprocessingData {
bool operator==(const LayerGroupPreprocessingData& other) const;
int lastLayerIdx;
bool layerBlendingEnabled;
std::vector<layergroupid::TypeID> layerType;
std::vector<layergroupid::BlendModeID> blendMode;
std::vector<layergroupid::AdjustmentTypeID> layerAdjustmentType;
};
bool operator==(const LayerShaderPreprocessingData& other) const;
static LayerShaderPreprocessingData get(const RenderableGlobe&);
std::array<LayerGroupPreprocessingData, layergroupid::NUM_LAYER_GROUPS>
layeredTextureInfo;
std::vector<std::pair<std::string, std::string>> keyValuePairs;
};
LayerShaderManager(std::string shaderName, std::string vsPath, std::string fsPath);
~LayerShaderManager();
/**
* Returns a pointer to a <code>ProgramObject</code> for rendering tiles.
*/
ghoul::opengl::ProgramObject* programObject() const;
bool updatedSinceLastCall();
void recompileShaderProgram(LayerShaderPreprocessingData preprocessingData);
private:
std::unique_ptr<ghoul::opengl::ProgramObject> _programObject;
LayerShaderPreprocessingData _preprocessingData;
const std::string _shaderName;
const std::string _vsPath;
const std::string _fsPath;
bool _updatedSinceLastCall = false;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___LAYER_SHADER_MANAGER___H__

View File

@@ -27,10 +27,10 @@
vec4 blendNormal(vec4 oldColor, vec4 newColor) {
vec4 toReturn;
toReturn.a = mix(oldColor.a, 1.0, newColor.a);
toReturn.rgb =
(newColor.rgb * newColor.a + oldColor.rgb * oldColor.a * (1 - newColor.a)) /
(newColor.a + oldColor.a * (1 - newColor.a));
toReturn.a = newColor.a + oldColor.a * (1 - newColor.a);
toReturn.a;
return toReturn;
}
@@ -46,28 +46,6 @@ vec4 blendSubtract(vec4 oldColor, vec4 newColor) {
return oldColor - newColor;
}
/*
vec3 rgb2hsv(vec3 c)
{
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
//vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
//vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
vec4 p = c.g < c.b ? vec4(c.bg, K.wz) : vec4(c.gb, K.xy);
vec4 q = c.r < p.x ? vec4(p.xyw, c.r) : vec4(c.r, p.yzx);
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
vec3 hsv2rgb(vec3 c)
{
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
*/
vec3 hsl2rgb(in vec3 c) {
vec3 rgb = clamp(abs(mod(c.x * 6.0 + vec3(0.0, 4.0, 2.0), 6.0) - 3.0) - 1.0, 0.0, 1.0);
@@ -78,30 +56,29 @@ vec3 HueShift(in vec3 color, in float shift) {
vec3 P = vec3(0.55735) * dot(vec3(0.55735), color);
vec3 U = color - P;
vec3 V = cross(vec3(0.55735), U);
vec3 c = U*cos(shift*6.2832) + V*sin(shift*6.2832) + P;
vec3 c = U * cos(shift*6.2832) + V * sin(shift*6.2832) + P;
return c;
}
vec3 rgb2hsl(in vec3 c) {
float h = 0.0;
float s = 0.0;
float l = 0.0;
float r = c.r;
float g = c.g;
float b = c.b;
float cMin = min(r, min(g, b));
float cMax = max(r, max(g, b));
l = (cMax + cMin) / 2.0;
if (cMax > cMin) {
float l = (cMax + cMin) / 2.0;
float cDelta = cMax - cMin;
//s = l < .05 ? cDelta / ( cMax + cMin ) : cDelta / ( 2.0 - ( cMax + cMin ) ); Original
s = (l < 0.0) ? cDelta / (cMax + cMin) : cDelta / (2.0 - (cMax + cMin));
float s = (l < 0.0) ? cDelta / (cMax + cMin) : cDelta / (2.0 - (cMax + cMin));
if ( r == cMax ) {
float h = 0.0;
if (r == cMax) {
h = (g - b) / cDelta;
} else if ( g == cMax ) {
} else if (g == cMax) {
h = 2.0 + (b - r) / cDelta;
} else {
h = 4.0 + (r - g) / cDelta;
@@ -111,14 +88,16 @@ vec3 rgb2hsl(in vec3 c) {
h += 6.0;
}
h = h / 6.0;
return vec3(h, s, l);
}
else {
return vec3(0.0);
}
return vec3(h, s, l);
}
vec3 rgb2hsv(vec3 c) {
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
//vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
//vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
vec4 p = (c.g < c.b) ? vec4(c.bg, K.wz) : vec4(c.gb, K.xy);
vec4 q = (c.r < p.x) ? vec4(p.xyw, c.r) : vec4(c.r, p.yzx);

View File

@@ -1,102 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef ELLIPSOID_HGLSL
#define ELLIPSOID_HGLSL
struct PositionNormalPair {
vec3 position;
vec3 normal;
};
struct Intersection {
bool intersects;
float nearParameter; // Along ray
float farParameter; // Along ray
};
vec3 geodeticSurfaceNormal(float latitude, float longitude) {
float cosLat = cos(latitude);
return vec3(
cosLat * cos(longitude),
cosLat * sin(longitude),
sin(latitude)
);
}
PositionNormalPair geodetic3ToCartesian(float latitude, float longitude, float height,
vec3 radiiSquared)
{
vec3 normal = geodeticSurfaceNormal(latitude, longitude);
vec3 k = radiiSquared * normal;
float gamma = sqrt(dot(k, normal));
vec3 rSurface = k / gamma;
PositionNormalPair toReturn;
toReturn.position = rSurface + height * normal;
toReturn.normal = normal;
return toReturn;
}
PositionNormalPair geodetic2ToCartesian(float latitude, float longitude,
vec3 radiiSquared)
{
// Position on surface : height = 0
return geodetic3ToCartesian(latitude, longitude, 0, radiiSquared);
}
vec3 latLonToCartesian(float latitude, float longitude, float radius) {
return radius * vec3(
cos(latitude) * cos(longitude),
cos(latitude) * sin(longitude),
sin(latitude)
);
}
//
// Assumes ellipsoid is at (0, 0, 0)
//
Intersection rayIntersectEllipsoid(vec3 rayOrigin, vec3 rayOriginSquared,
vec3 rayDirection, vec3 oneOverEllipsoidRadiiSquared)
{
float a = dot(rayDirection * rayDirection, oneOverEllipsoidRadiiSquared);
float b = 2.0 * dot(rayOrigin * rayDirection, oneOverEllipsoidRadiiSquared);
float c = dot(rayOriginSquared, oneOverEllipsoidRadiiSquared) - 1.0;
float discriminant = b * b - 4.0 * a * c;
if (discriminant < 0.0) {
return Intersection(false, 0.0, 0.0);
}
else if (discriminant == 0.0) {
float time = -0.5 * b / a;
return Intersection(true, time, time);
}
float t = -0.5 * (b + (b > 0.0 ? 1.0 : -1.0) * sqrt(discriminant));
float root1 = t / a;
float root2 = c / t;
return Intersection(true, min(root1, root2), max(root1, root2));
}
#endif // ELLIPSOID_HGLSL

View File

@@ -1,37 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <${MODULE_GLOBEBROWSING}/shaders/tilefragment.hglsl>
#include "fragment.glsl"
Fragment getFragment() {
Fragment frag;
frag = getTileFragment();
#if SHOW_CHUNK_EDGES
frag.color += patchBorderOverlay(fs_uv, vec3(0.0, 1.0, 0.0), 0.02);
#endif // SHOW_CHUNK_EDGES
return frag;
}

View File

@@ -25,7 +25,6 @@
#version __CONTEXT__
#include "PowerScaling/powerScaling_vs.hglsl"
#include <${MODULE_GLOBEBROWSING}/shaders/ellipsoid.hglsl>
#include <${MODULE_GLOBEBROWSING}/shaders/tile.hglsl>
#include <${MODULE_GLOBEBROWSING}/shaders/texturetilemapping.hglsl>
#include <${MODULE_GLOBEBROWSING}/shaders/tileheight.hglsl>
@@ -33,21 +32,21 @@
layout(location = 1) in vec2 in_uv;
out vec2 fs_uv;
out vec4 fs_position;
out vec3 fs_normal;
out vec2 fs_uv;
out vec3 ellipsoidNormalCameraSpace;
out LevelWeights levelWeights;
out vec3 levelWeights;
out vec3 positionCameraSpace;
#if USE_ACCURATE_NORMALS
out vec3 ellipsoidTangentThetaCameraSpace;
out vec3 ellipsoidTangentPhiCameraSpace;
#endif //USE_ACCURATE_NORMALS
out vec3 ellipsoidTangentThetaCameraSpace;
out vec3 ellipsoidTangentPhiCameraSpace;
#endif // USE_ACCURATE_NORMALS
#if USE_ECLIPSE_SHADOWS
out vec3 positionWorldSpace;
uniform dmat4 modelTransform;
out vec3 positionWorldSpace;
uniform dmat4 modelTransform;
#endif
uniform mat4 modelViewProjectionTransform;
@@ -63,49 +62,55 @@ uniform float distanceScaleFactor;
uniform int chunkLevel;
struct PositionNormalPair {
vec3 position;
vec3 normal;
};
PositionNormalPair globalInterpolation(vec2 uv) {
vec2 lonLatInput;
lonLatInput.y = minLatLon.y + lonLatScalingFactor.y * uv.y; // Lat
lonLatInput.x = minLatLon.x + lonLatScalingFactor.x * uv.x; // Lon
PositionNormalPair positionPairModelSpace = geodetic2ToCartesian(
lonLatInput.y,
lonLatInput.x,
radiiSquared
vec2 lonlat = lonLatScalingFactor * uv + minLatLon;
// geodetic surface normal
float cosLat = cos(lonlat.y);
vec3 normal = vec3(cosLat * cos(lonlat.x), cosLat * sin(lonlat.x), sin(lonlat.y));
vec3 k = radiiSquared * normal;
float gamma = sqrt(dot(k, normal));
PositionNormalPair result;
result.position = k / gamma;
result.normal = normal;
return result;
}
vec3 getLevelWeights(float distToVertexOnEllipsoid) {
float projectedScaleFactor = distanceScaleFactor / distToVertexOnEllipsoid;
float desiredLevel = log2(projectedScaleFactor);
float levelInterp = chunkLevel - desiredLevel;
return vec3(
clamp(1.0 - levelInterp, 0.0, 1.0),
clamp(levelInterp, 0.0, 1.0) - clamp(levelInterp - 1.0, 0.0, 1.0),
clamp(levelInterp - 1.0, 0.0, 1.0)
);
return positionPairModelSpace;
}
void main() {
PositionNormalPair pair = globalInterpolation(in_uv);
float distToVertexOnEllipsoid =
length(pair.position + pair.normal * chunkMinHeight - cameraPosition);
float levelInterpolationParameter =
getLevelInterpolationParameter(
chunkLevel,
distanceScaleFactor,
distToVertexOnEllipsoid);
float distToVertexOnEllipsoid = length((pair.normal * chunkMinHeight + pair.position) - cameraPosition);
// use level weight for height sampling, and output to fragment shader
levelWeights = getLevelWeights(levelInterpolationParameter);
levelWeights = getLevelWeights(distToVertexOnEllipsoid);
// Get the height value
float height = getTileHeight(in_uv, levelWeights);
// Apply skirts
height -= getTileVertexSkirtLength();
// Get the height value and apply skirts
float height = getTileHeight(in_uv, levelWeights) - getTileVertexSkirtLength();
#if USE_ACCURATE_NORMALS
// Calculate tangents
// tileDelta is a step length (epsilon). Should be small enough for accuracy but not
// Too small for precision. 1 / 512 is good.
const float tileDelta = 1.0 / 512.0;
PositionNormalPair pair10 = globalInterpolation(
in_uv + vec2(1.0, 0.0) * tileDelta
);
PositionNormalPair pair01 = globalInterpolation(
in_uv + vec2(0.0, 1.0) * tileDelta
);
PositionNormalPair pair10 = globalInterpolation(vec2(1.0, 0.0) * tileDelta + in_uv);
PositionNormalPair pair01 = globalInterpolation(vec2(0.0, 1.0) * tileDelta + in_uv);
vec3 ellipsoidTangentTheta = normalize(pair10.position - pair.position);
vec3 ellipsoidTangentPhi = normalize(pair01.position - pair.position);
ellipsoidTangentThetaCameraSpace = mat3(modelViewTransform) * ellipsoidTangentTheta;
@@ -113,9 +118,8 @@ void main() {
#endif // USE_ACCURATE_NORMALS
// Add the height in the direction of the normal
pair.position += pair.normal * height;
vec4 positionClippingSpace =
modelViewProjectionTransform * vec4(pair.position, 1.0);
pair.position = pair.normal * height + pair.position;
vec4 positionClippingSpace = modelViewProjectionTransform * vec4(pair.position, 1.0);
// Write output
fs_uv = in_uv;

View File

@@ -1,56 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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. *
****************************************************************************************/
#ifndef GLOBESHADING_HGLSL
#define GLOBESHADING_HGLSL
float orenNayarDiffuse(vec3 lightDirection, vec3 viewDirection, vec3 surfaceNormal,
float roughness)
{
// calculate intermediary values
float NdotL = dot(surfaceNormal, lightDirection);
float NdotV = dot(surfaceNormal, viewDirection);
float angleVN = acos(NdotV);
float angleLN = acos(NdotL);
float alpha = max(angleVN, angleLN);
float beta = min(angleVN, angleLN);
float gamma = dot(
viewDirection - surfaceNormal * dot(viewDirection, surfaceNormal),
lightDirection - surfaceNormal * dot(lightDirection, surfaceNormal)
);
float roughnessSquared = roughness * roughness;
// calculate A and B
float A = 1.0 - 0.5 * (roughnessSquared / (roughnessSquared + 0.57));
float B = 0.45 * (roughnessSquared / (roughnessSquared + 0.09));
float C = sin(alpha) * tan(beta);
// put it all together
return max(0.0, NdotL) * (A + B * max(0.0, gamma) * C);
}
#endif // GLOBESHADING_HGLSL

View File

@@ -1,37 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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 <${MODULE_GLOBEBROWSING}/shaders/tilefragment.hglsl>
#include "fragment.glsl"
Fragment getFragment() {
Fragment frag;
frag = getTileFragment();
#if SHOW_CHUNK_EDGES
frag.color += patchBorderOverlay(fs_uv, vec3(1,0,0), 0.005);
#endif // SHOW_CHUNK_EDGES
return frag;
}

View File

@@ -25,7 +25,6 @@
#version __CONTEXT__
#include "PowerScaling/powerScaling_vs.hglsl"
#include <${MODULE_GLOBEBROWSING}/shaders/ellipsoid.hglsl>
#include <${MODULE_GLOBEBROWSING}/shaders/tile.hglsl>
#include <${MODULE_GLOBEBROWSING}/shaders/texturetilemapping.hglsl>
#include <${MODULE_GLOBEBROWSING}/shaders/tileheight.hglsl>
@@ -37,12 +36,12 @@ out vec2 fs_uv;
out vec4 fs_position;
out vec3 fs_normal;
out vec3 ellipsoidNormalCameraSpace;
out LevelWeights levelWeights;
out vec3 levelWeights;
out vec3 positionCameraSpace;
#if USE_ACCURATE_NORMALS
out vec3 ellipsoidTangentThetaCameraSpace;
out vec3 ellipsoidTangentPhiCameraSpace;
out vec3 ellipsoidTangentThetaCameraSpace;
out vec3 ellipsoidTangentPhiCameraSpace;
#endif // USE_ACCURATE_NORMALS
#if USE_ECLIPSE_SHADOWS
@@ -64,10 +63,21 @@ uniform float distanceScaleFactor;
uniform int chunkLevel;
vec3 bilinearInterpolation(vec2 uv) {
vec3 p0 = (1 - uv.x) * p00 + uv.x * p10;
vec3 p1 = (1 - uv.x) * p01 + uv.x * p11;
vec3 p = (1 - uv.y) * p0 + uv.y * p1;
return p;
vec3 p0 = mix(p00, p10, uv.x);
vec3 p1 = mix(p01, p11, uv.x);
return mix(p0, p1, uv.y);
}
vec3 getLevelWeights(float distToVertexOnEllipsoid) {
float projectedScaleFactor = distanceScaleFactor / distToVertexOnEllipsoid;
float desiredLevel = log2(projectedScaleFactor);
float levelInterp = chunkLevel - desiredLevel;
return vec3(
clamp(1.0 - levelInterp, 0.0, 1.0),
clamp(levelInterp, 0.0, 1.0) - clamp(levelInterp - 1.0, 0.0, 1.0),
clamp(levelInterp - 1.0, 0.0, 1.0)
);
}
void main() {
@@ -76,31 +86,24 @@ void main() {
// Calculate desired level based on distance to the vertex on the ellipsoid
// Before any heightmapping is done
float distToVertexOnEllipsoid =
length(p + patchNormalCameraSpace * chunkMinHeight);
float levelInterpolationParameter =
getLevelInterpolationParameter(
chunkLevel,
distanceScaleFactor,
distToVertexOnEllipsoid);
float distToVertexOnEllipsoid = length(p + patchNormalCameraSpace * chunkMinHeight);
// use level weight for height sampling, and output to fragment shader
levelWeights = getLevelWeights(levelInterpolationParameter);
levelWeights = getLevelWeights(distToVertexOnEllipsoid);
// Get the height value and apply skirts
float height =
getTileHeightScaled(in_uv, levelWeights) - getTileVertexSkirtLength();
float height = getTileHeightScaled(in_uv, levelWeights) - getTileVertexSkirtLength();
// Translate the point along normal
p += patchNormalCameraSpace * height;
vec4 positionClippingSpace = projectionTransform * vec4(p, 1);
#if USE_ACCURATE_NORMALS
#if USE_ACCURATE_NORMALS
// Calculate tangents
ellipsoidTangentThetaCameraSpace = normalize(p10 - p00);
ellipsoidTangentPhiCameraSpace = normalize(p01 - p00);
#endif // USE_ACCURATE_NORMALS
#endif // USE_ACCURATE_NORMALS
// Write output
fs_uv = in_uv;
@@ -110,7 +113,7 @@ void main() {
fs_normal = patchNormalModelSpace;
positionCameraSpace = p;
#if USE_ECLIPSE_SHADOWS
#if USE_ECLIPSE_SHADOWS
positionWorldSpace = vec3(inverseViewTransform * dvec4(p, 1.0));
#endif
#endif
}

View File

@@ -1,44 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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"
in vec4 vs_positionClipSpace;
in vec2 vs_positionModelSpace;
//uniform vec3 directionToSunViewSpace;
uniform vec3 positionCameraSpace;
//uniform float lightOverflow;
Fragment getFragment() {
float alpha =
1.0 - sqrt(pow(vs_positionModelSpace.x, 2) + pow(vs_positionModelSpace.y, 2));
alpha = pow(alpha, 3);
Fragment frag;
frag.color = vec4(1.0, 1.0, 1.0, alpha);
frag.depth = vs_positionClipSpace.w;
frag.blend = BLEND_MODE_ADDITIVE;
return frag;
}

View File

@@ -1,54 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2018 *
* *
* 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__
#include "PowerScaling/powerScaling_vs.hglsl"
layout(location = 0) in vec2 in_position;
out vec4 vs_positionClipSpace;
out vec4 vs_positionCameraSpace;
out vec2 vs_positionModelSpace;
uniform float lightIntensityClamped;
uniform mat4 modelViewTransform;
uniform mat4 projectionTransform;
uniform mat4 directionToSunViewSpace;
void main() {
vs_positionModelSpace = in_position;
float totalIntensity = lightIntensityClamped;
vec4 positionCameraSpace = modelViewTransform * vec4(
in_position * totalIntensity,
0.0,
1.0
);
vec4 positionClipSpace = projectionTransform * positionCameraSpace;
vs_positionClipSpace = z_normalization(positionClipSpace);
gl_Position = z_normalization(positionClipSpace);
}

View File

@@ -22,14 +22,12 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef TILE_FRAG_COLOR_HGLSL
#define TILE_FRAG_COLOR_HGLSL
#include "fragment.glsl"
#include <${MODULE_GLOBEBROWSING}/shaders/tile.hglsl>
#include <${MODULE_GLOBEBROWSING}/shaders/texturetilemapping.hglsl>
#include <${MODULE_GLOBEBROWSING}/shaders/tileheight.hglsl>
#include "PowerScaling/powerScaling_fs.hglsl"
#include "fragment.glsl"
// Below are all the tiles that are used for contributing the actual fragment color
@@ -47,18 +45,13 @@ uniform Layer Overlays[NUMLAYERS_OVERLAY];
#if USE_WATERMASK
uniform Layer WaterMasks[NUMLAYERS_WATERMASK];
float waterReflectance = 0.0;
#endif // USE_WATERMASK
#if SHOW_HEIGHT_RESOLUTION
uniform vec2 vertexResolution;
#endif
#if USE_ATMOSPHERE
// TODO atmosphere uniforms here
#endif // USE_ATMOSPHERE
#if USE_NIGHTTEXTURE || USE_WATERMASK || USE_ATMOSPHERE || PERFORM_SHADING
#if USE_NIGHTTEXTURE || USE_WATERMASK || PERFORM_SHADING
uniform vec3 lightDirectionCameraSpace;
#endif
@@ -67,7 +60,6 @@ uniform float orenNayarRoughness;
#endif
#if USE_ECLIPSE_SHADOWS
in vec3 positionWorldSpace;
/*******************************************************************************
***** ALL CALCULATIONS FOR ECLIPSE ARE IN METERS AND IN WORLD SPACE SYSTEM ****
@@ -77,60 +69,61 @@ in vec3 positionWorldSpace;
const uint numberOfShadows = 1;
struct ShadowRenderingStruct {
double xu, xp;
double rs, rc;
dvec3 sourceCasterVec;
dvec3 casterPositionVec;
bool isShadowing;
double xu, xp;
double rs, rc;
dvec3 sourceCasterVec;
dvec3 casterPositionVec;
bool isShadowing;
};
// Eclipse shadow data
// JCC: Remove and use dictionary to
// JCC: Remove and use dictionary to
// decides the number of shadows
uniform ShadowRenderingStruct shadowDataArray[numberOfShadows];
uniform int shadows;
uniform bool hardShadows;
vec4 butterworthFunc(const float d, const float r, const float n) {
return vec4(vec3(sqrt(r/(r + pow(d, 2*n)))), 1.0);
}
vec4 calcShadow(const ShadowRenderingStruct shadowInfoArray[numberOfShadows], const dvec3 position,
const bool ground) {
vec4 calcShadow(const ShadowRenderingStruct shadowInfoArray[numberOfShadows],
const dvec3 position, const bool ground)
{
if (shadowInfoArray[0].isShadowing) {
dvec3 pc = shadowInfoArray[0].casterPositionVec - position;
dvec3 sc_norm = shadowInfoArray[0].sourceCasterVec;
dvec3 pc_proj = dot(pc, sc_norm) * sc_norm;
dvec3 d = pc - pc_proj;
float length_d = float(length(d));
double length_pc_proj = length(pc_proj);
float r_p_pi = float(shadowInfoArray[0].rc * (length_pc_proj + shadowInfoArray[0].xp) / shadowInfoArray[0].xp);
float r_u_pi = float(shadowInfoArray[0].rc * (shadowInfoArray[0].xu - length_pc_proj) / shadowInfoArray[0].xu);
if ( length_d < r_u_pi ) { // umbra
if (length_d < r_u_pi) { // umbra
if (ground) {
#if USE_ECLIPSE_HARD_SHADOWS
#if USE_ECLIPSE_HARD_SHADOWS
return vec4(0.2, 0.2, 0.2, 1.0);
#else
// butterworthFunc
return vec4(vec3(sqrt(r_u_pi / (r_u_pi + pow(length_d, 8.0)))), 1.0);
#endif
return butterworthFunc(length_d, r_u_pi, 4.0);
}
else {
#if USE_ECLIPSE_HARD_SHADOWS
#if USE_ECLIPSE_HARD_SHADOWS
return vec4(0.5, 0.5, 0.5, 1.0);
#endif
return vec4(vec3(length_d/r_p_pi), 1.0);
#else
return vec4(vec3(length_d / r_p_pi), 1.0);
#endif
}
}
else if ( length_d < r_p_pi ) {// penumbra
#if USE_ECLIPSE_HARD_SHADOWS
return vec4(0.5, 0.5, 0.5, 1.0);
#endif
return vec4(vec3(length_d/r_p_pi), 1.0);
else if (length_d < r_p_pi) {// penumbra
#if USE_ECLIPSE_HARD_SHADOWS
return vec4(0.5, 0.5, 0.5, 1.0);
#else
return vec4(vec3(length_d / r_p_pi), 1.0);
#endif
}
}
return vec4(1.0);
}
#endif
@@ -139,28 +132,27 @@ in vec4 fs_position;
in vec3 fs_normal;
in vec2 fs_uv;
in vec3 ellipsoidNormalCameraSpace;
in vec3 levelWeights;
in vec3 positionCameraSpace;
#if USE_ACCURATE_NORMALS
in vec3 ellipsoidTangentThetaCameraSpace;
in vec3 ellipsoidTangentPhiCameraSpace;
in vec3 ellipsoidTangentThetaCameraSpace;
in vec3 ellipsoidTangentPhiCameraSpace;
// Once deferred light calculations are done in view space this can be removed
// so that we only need one normal; in view space.
uniform mat4 invViewModelTransform;
// Once deferred light calculations are done in view space this can be removed
// so that we only need one normal; in view space.
uniform mat4 invViewModelTransform;
#endif // USE_ACCURATE_NORMALS
// levelInterpolationParameter is used to interpolate between a tile and its parent tiles
// The value increases with the distance from the vertex (or fragment) to the camera
in LevelWeights levelWeights;
#if USE_ECLIPSE_SHADOWS
in vec3 positionWorldSpace;
#endif // USE_ECLIPSE_SHADOWS
/**
* This method defines the fragment color pipeline which is used in both
* the local and global chunk rendering.
*
*/
Fragment getTileFragment() {
Fragment getFragment() {
Fragment frag;
frag.color = vec4(0.3, 0.3, 0.3, 1.0);
vec3 normal = normalize(ellipsoidNormalCameraSpace);
@@ -179,15 +171,11 @@ Fragment getTileFragment() {
#endif /// USE_ACCURATE_NORMALS
#if USE_COLORTEXTURE
frag.color = calculateColor(
frag.color,
fs_uv,
levelWeights,
ColorLayers
);
frag.color = calculateColor(frag.color, fs_uv, levelWeights, ColorLayers);
#endif // USE_COLORTEXTURE
#if USE_WATERMASK
float waterReflectance = 0.0;
frag.color = calculateWater(
frag.color,
fs_uv,
@@ -223,45 +211,16 @@ Fragment getTileFragment() {
);
#endif // PERFORM_SHADING
#if USE_ATMOSPHERE
// Temporary until the real atmosphere code is here
//frag.color = frag.color + vec4(0.5,0.5,1,0) * 0.3; // Just to see something for now
const vec3 n = normalize(ellipsoidNormalCameraSpace);
const vec3 l = lightDirectionCameraSpace;
const vec3 c = normalize(positionCameraSpace);
float cosFactor = 1 - clamp(dot(-n * 0.9, c), 0, 1);
cosFactor *= 1.1;
cosFactor -= 0.1;
cosFactor = clamp(cosFactor, 0.0, 1.0);
cosFactor = cosFactor + pow(cosFactor, 5);
const float shadowLight = 0.15;
float cosFactorLight = pow(max(dot(-l, n), -shadowLight) + shadowLight, 0.8);
//float cosFactorScatter = pow(max(dot(l, n) + shadowLight, 0), 5);
//float cosFactorLight = max(dot(-lightDirectionCameraSpace, normalize(ellipsoidNormalCameraSpace)), 0);
//vec3 r = reflect(l, n);
//float scatteredLight = pow(clamp(dot(-r,c), 0, 1), 20);
const vec3 atmosphereColor = vec3(0.5, 0.5, 1.0) * 2.0;
frag.color += vec4(atmosphereColor,0) * cosFactor * cosFactorLight * 0.5;
#endif // USE_ATMOSPHERE
#if USE_ECLIPSE_SHADOWS
frag.color *= calcShadow(shadowDataArray, dvec3(positionWorldSpace), true);
#endif
#if USE_OVERLAY
frag.color = calculateOverlay(
frag.color,
fs_uv,
levelWeights,
Overlays
);
frag.color = calculateOverlay(frag.color, fs_uv, levelWeights, Overlays);
#endif // USE_OVERLAY
#if SHOW_HEIGHT_INTENSITIES
frag.color.r *= 0.1;
frag.color.g *= 0.1;
frag.color.b *= 0.1;
frag.color.rgb *= vec3(0.1);
float untransformedHeight = getUntransformedTileVertexHeight(fs_uv, levelWeights);
float contourLine = fract(10.0 * untransformedHeight) > 0.98 ? 1.0 : 0.0;
@@ -270,7 +229,7 @@ Fragment getTileFragment() {
#endif
#if SHOW_HEIGHT_RESOLUTION
frag.color += 0.0001*calculateDebugColor(fs_uv, fs_position, vertexResolution);
frag.color += 0.0001 * calculateDebugColor(fs_uv, fs_position, vertexResolution);
#if USE_HEIGHTMAP
frag.color.r = min(frag.color.r, 0.8);
frag.color.r += tileResolution(fs_uv, HeightLayers[0].pile.chunkTile0) > 0.9 ? 1 : 0;
@@ -292,7 +251,18 @@ Fragment getTileFragment() {
frag.gPosition = vec4(positionCameraSpace, 1.0); // in Camera Rig Space
frag.depth = fs_position.w;
#if SHOW_CHUNK_EDGES
const float BorderSize = 0.005;
const vec3 BorderColor = vec3(1.0, 0.0, 0.0);
vec2 uvOffset = fs_uv - vec2(0.5);
float thres = 0.5 - BorderSize * 0.5;
bool isBorder = abs(uvOffset.x) > thres || abs(uvOffset.y) > thres;
if (isBorder) {
frag.color.rgb += BorderColor;
}
#endif // SHOW_CHUNK_EDGES
return frag;
}
#endif ///TILE_FRAG_COLOR_HGLSL

View File

@@ -27,7 +27,6 @@
#include <${MODULE_GLOBEBROWSING}/shaders/tile.hglsl>
#include <${MODULE_GLOBEBROWSING}/shaders/blending.hglsl>
#include <${MODULE_GLOBEBROWSING}/shaders/globeshading.hglsl>
// First layer type from LayerShaderManager is height map
#define NUMLAYERS_HEIGHTMAP #{lastLayerIndexHeightLayers} + 1
@@ -58,7 +57,6 @@
#define CHUNK_DEFAULT_HEIGHT #{defaultHeight}
// Other key value pairs used for settings
#define USE_ATMOSPHERE #{useAtmosphere}
#define USE_ACCURATE_NORMALS #{useAccurateNormals}
#define PERFORM_SHADING #{performShading}
#define USE_ECLIPSE_SHADOWS #{useEclipseShadows}
@@ -67,58 +65,88 @@
#define SHOW_HEIGHT_RESOLUTION #{showHeightResolution}
#define SHOW_HEIGHT_INTENSITIES #{showHeightIntensities}
float performLayerSettingsRGB(float currentValue, LayerSettings settings) {
float newValue = currentValue;
const vec3 DefaultLevelWeights = vec3(1.0, 0.0, 0.0);
newValue = sign(newValue) * pow(abs(newValue), settings.gamma);
newValue = newValue * settings.multiplier;
newValue = newValue + settings.offset;
float orenNayarDiffuse(vec3 lightDirection, vec3 viewDirection, vec3 surfaceNormal,
float roughness)
{
// calculate intermediary values
float NdotL = dot(surfaceNormal, lightDirection);
float NdotV = dot(surfaceNormal, viewDirection);
return newValue;
}
vec4 performLayerSettingsRGB(vec4 currentValue, LayerSettings settings) {
vec4 newValue = vec4(
performLayerSettingsRGB(currentValue.r, settings),
performLayerSettingsRGB(currentValue.g, settings),
performLayerSettingsRGB(currentValue.b, settings),
currentValue.a
float angleVN = acos(NdotV);
float angleLN = acos(NdotL);
float alpha = max(angleVN, angleLN);
float beta = min(angleVN, angleLN);
float gamma = dot(
viewDirection - surfaceNormal * dot(viewDirection, surfaceNormal),
lightDirection - surfaceNormal * dot(lightDirection, surfaceNormal)
);
return newValue;
}
float performLayerSettingsAlpha(float currentValue, LayerSettings settings) {
return currentValue * settings.opacity;
}
vec4 performLayerSettingsAlpha(vec4 currentValue, LayerSettings settings) {
return vec4(currentValue.rgb, performLayerSettingsAlpha(currentValue.a, settings));
float roughnessSquared = roughness * roughness;
// calculate A and B
float A = 1.0 - 0.5 * (roughnessSquared / (roughnessSquared + 0.57));
float B = 0.45 * (roughnessSquared / (roughnessSquared + 0.09));
float C = sin(alpha) * tan(beta);
// put it all together
return max(0.0, NdotL) * (A + B * max(0.0, gamma) * C);
}
float performLayerSettings(float currentValue, LayerSettings settings) {
return performLayerSettingsAlpha(
performLayerSettingsRGB(currentValue, settings),
settings
);
float v = sign(currentValue) * pow(abs(currentValue), settings.gamma) *
settings.multiplier + settings.offset;
return v * settings.opacity;
}
vec4 performLayerSettings(vec4 currentValue, LayerSettings settings) {
return performLayerSettingsAlpha(
performLayerSettingsRGB(currentValue, settings),
settings
);
vec3 newValue = sign(currentValue.rgb) * pow(abs(currentValue.rgb), vec3(settings.gamma)) *
settings.multiplier + settings.offset;
return vec4(newValue, currentValue.a * settings.opacity);
}
vec2 tileUVToTextureSamplePosition(ChunkTile chunkTile, vec2 tileUV,
PixelPadding padding)
{
vec2 uv = chunkTile.uvTransform.uvOffset + chunkTile.uvTransform.uvScale * tileUV;
// compensateSourceTextureSampling
ivec2 resolution = textureSize(chunkTile.textureSampler, 0);
vec2 sourceSize = vec2(resolution) + padding.sizeDifference;
vec2 currentSize = vec2(resolution);
vec2 sourceToCurrentSize = currentSize / sourceSize;
return sourceToCurrentSize * (uv - padding.startOffset / sourceSize);
}
vec4 getTexVal(ChunkTilePile chunkTilePile, vec3 w, vec2 uv,
PixelPadding padding)
{
vec4 v1 = texture(
chunkTilePile.chunkTile0.textureSampler,
tileUVToTextureSamplePosition(chunkTilePile.chunkTile0, uv, padding)
);
vec4 v2 = texture(
chunkTilePile.chunkTile1.textureSampler,
tileUVToTextureSamplePosition(chunkTilePile.chunkTile1, uv, padding)
);
vec4 v3 = texture(
chunkTilePile.chunkTile2.textureSampler,
tileUVToTextureSamplePosition(chunkTilePile.chunkTile2, uv, padding)
);
return w.x * v1 + w.y * v2 + w.z * v3;
}
#for id, layerGroup in layerGroups
#for i in 0..#{lastLayerIndex#{layerGroup}}
vec4 getSample#{layerGroup}#{i}(vec2 uv, LevelWeights levelWeights,
vec4 getSample#{layerGroup}#{i}(vec2 uv, vec3 levelWeights,
Layer #{layerGroup}[#{lastLayerIndex#{layerGroup}} + 1])
{
vec4 color = vec4(0,0,0,1);
vec4 color = vec4(0.0, 0.0, 0.0, 1.0);
// All tile layers are the same. Sample from texture
#if (#{#{layerGroup}#{i}LayerType} == 0) // DefaultTileLayer
color = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv, #{layerGroup}[#{i}].padding);
@@ -203,7 +231,7 @@ vec4 performAdjustment#{layerGroup}#{i}(vec4 currentColor,
#endfor
#endfor
float calculateUntransformedHeight(vec2 uv, LevelWeights levelWeights,
float calculateUntransformedHeight(vec2 uv, vec3 levelWeights,
Layer HeightLayers[NUMLAYERS_HEIGHTMAP])
{
@@ -212,7 +240,7 @@ float calculateUntransformedHeight(vec2 uv, LevelWeights levelWeights,
// The shader compiler will remove unused code when variables are multiplied by
// a constant 0
#if !HEIGHTMAP_BLENDING_ENABLED
levelWeights = getDefaultLevelWeights();
levelWeights = DefaultLevelWeights;
#endif // HEIGHTMAP_BLENDING_ENABLED
#for i in 0..#{lastLayerIndexHeightLayers}
@@ -227,17 +255,14 @@ float calculateUntransformedHeight(vec2 uv, LevelWeights levelWeights,
return height;
}
float calculateHeight(
vec2 uv,
LevelWeights levelWeights,
Layer HeightLayers[NUMLAYERS_HEIGHTMAP]) {
float calculateHeight(vec2 uv, vec3 levelWeights, Layer HeightLayers[NUMLAYERS_HEIGHTMAP])
{
float height = 0;
// The shader compiler will remove unused code when variables are multiplied by
// a constant 0
#if !HEIGHTMAP_BLENDING_ENABLED
levelWeights = getDefaultLevelWeights();
levelWeights = DefaultLevelWeights;
#endif // HEIGHTMAP_BLENDING_ENABLED
@@ -247,7 +272,9 @@ float calculateHeight(
colorSample = performAdjustmentHeightLayers#{i}(colorSample, HeightLayers[#{i}].adjustment);
float untransformedHeight = colorSample.r;
float heightSample = getTransformedTexVal(HeightLayers[#{i}].depthTransform, untransformedHeight);
TileDepthTransform transform = HeightLayers[#{i}].depthTransform;
float heightSample =
transform.depthScale * untransformedHeight + transform.depthOffset;
if (heightSample > -100000) {
heightSample = performLayerSettings(heightSample, HeightLayers[#{i}].settings);
height = heightSample;
@@ -257,7 +284,7 @@ float calculateHeight(
return height;
}
vec4 calculateColor(vec4 currentColor, vec2 uv, LevelWeights levelWeights,
vec4 calculateColor(vec4 currentColor, vec2 uv, vec3 levelWeights,
Layer ColorLayers[NUMLAYERS_COLORTEXTURE])
{
vec4 color = currentColor;
@@ -265,7 +292,7 @@ vec4 calculateColor(vec4 currentColor, vec2 uv, LevelWeights levelWeights,
// The shader compiler will remove unused code when variables are multiplied by
// a constant 0
#if !COLORTEXTURE_BLENDING_ENABLED
levelWeights = getDefaultLevelWeights();
levelWeights = DefaultLevelWeights;
#endif // COLORTEXTURE_BLENDING_ENABLED
#for i in 0..#{lastLayerIndexColorLayers}
@@ -278,20 +305,20 @@ vec4 calculateColor(vec4 currentColor, vec2 uv, LevelWeights levelWeights,
}
#endfor
return color;
return color;
}
float gridDots(vec2 uv, vec2 gridResolution){
float gridDots(vec2 uv, vec2 gridResolution) {
vec2 uvVertexSpace = fract((gridResolution) * uv) + 0.5;
vec2 uvDotSpace = abs(2*(uvVertexSpace-0.5));
return 1-length(1-uvDotSpace);
vec2 uvDotSpace = abs(2.0 * (uvVertexSpace - 0.5));
return 1.0 - length(1.0 - uvDotSpace);
}
vec4 calculateDebugColor(vec2 uv, vec4 fragPos, vec2 vertexResolution) {
vec2 uvVertexSpace = fract(vertexResolution * uv);
vec3 colorUv = vec3(0.3 * uv.x, 0.3 * uv.y, 0);
vec3 colorDistance = vec3(0, 0, min( 0.4 * log(fragPos.w) - 3.9, 1));
vec3 colorDistance = vec3(0.0, 0.0, min(0.4 * log(fragPos.w) - 3.9, 1));
vec3 colorVertex = (1.0 - length(uvVertexSpace)) * vec3(0.5);
vec3 colorSum = colorUv + colorDistance + colorVertex;
return vec4(0.5 * colorSum, 1);
@@ -303,12 +330,12 @@ float tileResolution(vec2 tileUV, ChunkTile chunkTile) {
padding.sizeDifference = ivec2(0);
vec2 heightResolution = textureSize(chunkTile.textureSampler, 0);
vec2 uv = TileUVToTextureSamplePosition(chunkTile, tileUV, padding);
vec2 uv = tileUVToTextureSamplePosition(chunkTile, tileUV, padding);
return gridDots(uv, heightResolution);
}
vec4 calculateNight(vec4 currentColor, vec2 uv, LevelWeights levelWeights,
Layer NightLayers[NUMLAYERS_NIGHTTEXTURE],
vec4 calculateNight(vec4 currentColor, vec2 uv, vec3 levelWeights,
Layer NightLayers[NUMLAYERS_NIGHTTEXTURE],
vec3 ellipsoidNormalCameraSpace,
vec3 lightDirectionCameraSpace)
{
@@ -318,7 +345,7 @@ vec4 calculateNight(vec4 currentColor, vec2 uv, LevelWeights levelWeights,
// The shader compiler will remove unused code when variables are multiplied by
// a constant 0
#if !NIGHTTEXTURE_BLENDING_ENABLED
levelWeights = getDefaultLevelWeights();
levelWeights = DefaultLevelWeights;
#endif // NIGHTTEXTURE_BLENDING_ENABLED
vec3 n = normalize(ellipsoidNormalCameraSpace);
@@ -363,7 +390,7 @@ vec4 calculateShadedColor(vec4 currentColor, vec3 ellipsoidNormalCameraSpace,
return color;
}
vec4 calculateOverlay(vec4 currentColor, vec2 uv, LevelWeights levelWeights,
vec4 calculateOverlay(vec4 currentColor, vec2 uv, vec3 levelWeights,
Layer Overlays[NUMLAYERS_OVERLAY])
{
vec4 color = currentColor;
@@ -371,7 +398,7 @@ vec4 calculateOverlay(vec4 currentColor, vec2 uv, LevelWeights levelWeights,
// The shader compiler will remove unused code when variables are multiplied by
// a constant 0
#if !OVERLAY_BLENDING_ENABLED
levelWeights = getDefaultLevelWeights();
levelWeights = DefaultLevelWeights;
#endif // OVERLAY_BLENDING_ENABLED
#for i in 0..#{lastLayerIndexOverlays}
@@ -389,7 +416,7 @@ vec4 calculateOverlay(vec4 currentColor, vec2 uv, LevelWeights levelWeights,
return color;
}
vec4 calculateWater(vec4 currentColor, vec2 uv, LevelWeights levelWeights,
vec4 calculateWater(vec4 currentColor, vec2 uv, vec3 levelWeights,
Layer WaterMasks[NUMLAYERS_WATERMASK],
vec3 ellipsoidNormalCameraSpace,
vec3 lightDirectionCameraSpace, vec3 positionCameraSpace,
@@ -400,7 +427,7 @@ vec4 calculateWater(vec4 currentColor, vec2 uv, LevelWeights levelWeights,
// The shader compiler will remove unused code when variables are multiplied by
// a constant 0
#if !WATERMASK_BLENDING_ENABLED
levelWeights = getDefaultLevelWeights();
levelWeights = DefaultLevelWeights;
#endif // WATERMASK_BLENDING_ENABLED
#for i in 0..#{lastLayerIndexWaterMasks}
@@ -408,8 +435,7 @@ vec4 calculateWater(vec4 currentColor, vec2 uv, LevelWeights levelWeights,
vec4 colorSample = getSampleWaterMasks#{i}(uv, levelWeights, WaterMasks);
colorSample = performAdjustmentWaterMasks#{i}(colorSample, WaterMasks[#{i}].adjustment);
colorSample = performLayerSettingsAlpha(colorSample, WaterMasks[#{i}].settings);
colorSample.a = performLayerSettingsRGB(colorSample.a, WaterMasks[#{i}].settings);
colorSample.a = performLayerSettings(colorSample.a, WaterMasks[#{i}].settings);
waterColor = blendWaterMasks#{i}(waterColor, colorSample, 1.0);
}
@@ -420,8 +446,8 @@ vec4 calculateWater(vec4 currentColor, vec2 uv, LevelWeights levelWeights,
float cosineFactor = clamp(dot(-reflectionDirectionCameraSpace, directionToFragmentCameraSpace), 0, 1);
cosineFactor = pow(cosineFactor, 100);
vec3 specularColor = vec3(1, 1, 1);
float specularIntensity = 0.4;
const vec3 specularColor = vec3(1.0);
const float specularIntensity = 0.4;
vec3 specularTotal = specularColor * cosineFactor * specularIntensity * waterColor.a;

View File

@@ -75,91 +75,4 @@ struct Layer {
vec3 color;
};
struct LevelWeights {
float w1;
float w2;
float w3;
};
vec4 patchBorderOverlay(vec2 uv, vec3 borderColor, float borderSize) {
vec2 uvOffset = uv - vec2(0.5);
float thres = 0.5 - borderSize/2;
bool isBorder = abs(uvOffset.x) > thres || abs(uvOffset.y) > thres;
vec3 color = isBorder ? borderColor : vec3(0);
return vec4(color, 0);
}
float getTransformedTexVal(TileDepthTransform transform, float val) {
return transform.depthOffset + transform.depthScale * val;
}
vec4 getTransformedTexVal(TileDepthTransform transform, vec4 val) {
return transform.depthOffset + transform.depthScale * val;
}
vec2 compensateSourceTextureSampling(vec2 startOffset, vec2 sizeDiff, ChunkTile chunkTile,
vec2 tileUV)
{
ivec2 resolution = textureSize(chunkTile.textureSampler, 0);
vec2 sourceSize = vec2(resolution) + sizeDiff;
vec2 currentSize = vec2(resolution);
vec2 sourceToCurrentSize = currentSize / sourceSize;
return sourceToCurrentSize * (tileUV - startOffset / sourceSize);
}
vec2 TileUVToTextureSamplePosition(ChunkTile chunkTile, vec2 tileUV,
PixelPadding padding)
{
vec2 uv = chunkTile.uvTransform.uvOffset + chunkTile.uvTransform.uvScale * tileUV;
return compensateSourceTextureSampling(
padding.startOffset,
padding.sizeDifference,
chunkTile,
uv
);
}
vec4 getTexVal(ChunkTile chunkTile, vec2 tileUV, PixelPadding padding) {
return texture(
chunkTile.textureSampler,
TileUVToTextureSamplePosition(chunkTile, tileUV, padding)
);
}
float getLevelInterpolationParameter(int chunkLevel, float distanceScaleFactor,
float distToVertexOnEllipsoid)
{
float projectedScaleFactor = distanceScaleFactor / distToVertexOnEllipsoid;
float desiredLevel = log2(projectedScaleFactor);
return chunkLevel - desiredLevel;
}
LevelWeights getLevelWeights(float levelInterpolationParameter) {
LevelWeights levelWeights;
levelWeights.w1 = clamp(1.0 - levelInterpolationParameter, 0.0, 1.0);
levelWeights.w2 = (
clamp(levelInterpolationParameter, 0.0, 1.0) -
clamp(levelInterpolationParameter - 1.0, 0.0, 1.0)
);
levelWeights.w3 = clamp(levelInterpolationParameter - 1.0, 0.0, 1.0);
return levelWeights;
}
LevelWeights getDefaultLevelWeights() {
LevelWeights levelWeights;
levelWeights.w1 = 1;
levelWeights.w2 = 0;
levelWeights.w3 = 0;
return levelWeights;
}
vec4 getTexVal(ChunkTilePile chunkTilePile, LevelWeights w, vec2 uv,
PixelPadding padding)
{
return w.w1 * getTexVal(chunkTilePile.chunkTile0, uv, padding) +
w.w2 * getTexVal(chunkTilePile.chunkTile1, uv, padding) +
w.w3 * getTexVal(chunkTilePile.chunkTile2, uv, padding);
}
#endif // TEXTURETILE_HGLSL

View File

@@ -28,7 +28,6 @@
#include "PowerScaling/powerScaling_vs.hglsl"
#include <${MODULE_GLOBEBROWSING}/shaders/tile.hglsl>
#include <${MODULE_GLOBEBROWSING}/shaders/ellipsoid.hglsl>
#ifndef USE_HEIGHTMAP
#define USE_HEIGHTMAP #{useAccurateNormals}
@@ -51,7 +50,7 @@ uniform float deltaPhi1;
uniform float tileDelta;
#endif //USE_ACCURATE_NORMALS && USE_HEIGHTMAP
float getUntransformedTileHeight(vec2 uv, LevelWeights levelWeights) {
float getUntransformedTileHeight(vec2 uv, vec3 levelWeights) {
float height = CHUNK_DEFAULT_HEIGHT;
#if USE_HEIGHTMAP
@@ -67,7 +66,7 @@ float getUntransformedTileHeight(vec2 uv, LevelWeights levelWeights) {
return height;
}
float getTileHeight(vec2 uv, LevelWeights levelWeights) {
float getTileHeight(vec2 uv, vec3 levelWeights) {
float height = CHUNK_DEFAULT_HEIGHT;
#if USE_HEIGHTMAP
@@ -83,7 +82,7 @@ float getTileHeight(vec2 uv, LevelWeights levelWeights) {
return height;
}
float getTileHeightScaled(vec2 uv, LevelWeights levelWeights) {
float getTileHeightScaled(vec2 uv, vec3 levelWeights) {
float height = getTileHeight(uv, levelWeights);
#if USE_HEIGHTMAP
@@ -93,7 +92,7 @@ float getTileHeightScaled(vec2 uv, LevelWeights levelWeights) {
return height;
}
vec3 getTileNormal(vec2 uv, LevelWeights levelWeights, vec3 ellipsoidNormalCameraSpace,
vec3 getTileNormal(vec2 uv, vec3 levelWeights, vec3 ellipsoidNormalCameraSpace,
vec3 ellipsoidTangentThetaCameraSpace,
vec3 ellipsoidTangentPhiCameraSpace)
{

View File

@@ -22,13 +22,12 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/globebrowsing/tile/asynctiledataprovider.h>
#include <modules/globebrowsing/src/asynctiledataprovider.h>
#include <modules/globebrowsing/cache/memoryawaretilecache.h>
#include <modules/globebrowsing/globebrowsingmodule.h>
#include <modules/globebrowsing/other/pixelbuffercontainer.h>
#include <modules/globebrowsing/tile/tileloadjob.h>
#include <modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.h>
#include <modules/globebrowsing/src/memoryawaretilecache.h>
#include <modules/globebrowsing/src/rawtiledatareader.h>
#include <modules/globebrowsing/src/tileloadjob.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/engine/globals.h>
#include <ghoul/logging/logmanager.h>
@@ -41,7 +40,7 @@ namespace {
} // namespace
AsyncTileDataProvider::AsyncTileDataProvider(std::string name,
const std::shared_ptr<RawTileDataReader> rawTileDataReader)
std::unique_ptr<RawTileDataReader> rawTileDataReader)
: _name(std::move(name))
, _rawTileDataReader(std::move(rawTileDataReader))
, _concurrentJobManager(LRUThreadPool<TileIndex::TileHashKey>(1, 10))
@@ -52,72 +51,49 @@ AsyncTileDataProvider::AsyncTileDataProvider(std::string name,
AsyncTileDataProvider::~AsyncTileDataProvider() {} // NOLINT
std::shared_ptr<RawTileDataReader> AsyncTileDataProvider::rawTileDataReader() const {
return _rawTileDataReader;
const RawTileDataReader& AsyncTileDataProvider::rawTileDataReader() const {
return *_rawTileDataReader;
}
bool AsyncTileDataProvider::enqueueTileIO(const TileIndex& tileIndex) {
if (_resetMode == ResetMode::ShouldNotReset && satisfiesEnqueueCriteria(tileIndex)) {
if (_pboContainer) {
char* dataPtr = static_cast<char*>(_pboContainer->mapBuffer(
tileIndex.hashKey(), PixelBuffer::Access::WriteOnly));
if (dataPtr) {
auto job = std::make_shared<TileLoadJob>(_rawTileDataReader, tileIndex,
dataPtr);
_concurrentJobManager.enqueueJob(job, tileIndex.hashKey());
_enqueuedTileRequests.insert(tileIndex.hashKey());
}
else {
return false;
}
}
else {
auto job = std::make_shared<TileLoadJob>(_rawTileDataReader, tileIndex);
_concurrentJobManager.enqueueJob(job, tileIndex.hashKey());
_enqueuedTileRequests.insert(tileIndex.hashKey());
}
auto job = std::make_unique<TileLoadJob>(*_rawTileDataReader, tileIndex);
_concurrentJobManager.enqueueJob(std::move(job), tileIndex.hashKey());
_enqueuedTileRequests.insert(tileIndex.hashKey());
return true;
}
return false;
}
std::vector<std::shared_ptr<RawTile>> AsyncTileDataProvider::rawTiles() {
std::vector<std::shared_ptr<RawTile>> readyResults;
std::shared_ptr<RawTile> finishedJob = popFinishedRawTile();
std::vector<RawTile> AsyncTileDataProvider::rawTiles() {
std::vector<RawTile> readyResults;
std::optional<RawTile> finishedJob = popFinishedRawTile();
while (finishedJob) {
readyResults.push_back(finishedJob);
readyResults.push_back(std::move(finishedJob.value()));
finishedJob = popFinishedRawTile();
}
return readyResults;
}
std::shared_ptr<RawTile> AsyncTileDataProvider::popFinishedRawTile() {
std::optional<RawTile> AsyncTileDataProvider::popFinishedRawTile() {
if (_concurrentJobManager.numFinishedJobs() > 0) {
// Now the tile load job looses ownerwhip of the data pointer
std::shared_ptr<RawTile> product =
_concurrentJobManager.popFinishedJob()->product();
RawTile product = _concurrentJobManager.popFinishedJob()->product();
const TileIndex::TileHashKey key = product->tileIndex.hashKey();
const TileIndex::TileHashKey key = product.tileIndex.hashKey();
// No longer enqueued. Remove from set of enqueued tiles
_enqueuedTileRequests.erase(key);
// Pbo is still mapped. Set the id for the raw tile
if (_pboContainer) {
product->pbo = _pboContainer->idOfMappedBuffer(key);
// Now we are finished with the mapping of this pbo
_pboContainer->unMapBuffer(key);
}
else {
product->pbo = 0;
if (product->error != RawTile::ReadError::None) {
delete[] product->imageData;
return nullptr;
}
product.pbo = 0;
if (product.error != RawTile::ReadError::None) {
product.imageData = nullptr;
return std::nullopt;
}
return product;
}
else {
return nullptr;
return std::nullopt;
}
}
@@ -137,10 +113,6 @@ void AsyncTileDataProvider::endUnfinishedJobs() {
std::vector<TileIndex::TileHashKey> unfinishedJobs =
_concurrentJobManager.keysToUnfinishedJobs();
for (const TileIndex::TileHashKey& unfinishedJob : unfinishedJobs) {
// Unmap unfinished jobs
if (_pboContainer) {
_pboContainer->unMapBuffer(unfinishedJob);
}
// When erasing the job before
_enqueuedTileRequests.erase(unfinishedJob);
}
@@ -150,31 +122,11 @@ void AsyncTileDataProvider::endEnqueuedJobs() {
std::vector<TileIndex::TileHashKey> enqueuedJobs =
_concurrentJobManager.keysToEnqueuedJobs();
for (const TileIndex::TileHashKey& enqueuedJob : enqueuedJobs) {
// Unmap unfinished jobs
if (_pboContainer) {
_pboContainer->unMapBuffer(enqueuedJob);
}
// When erasing the job before
_enqueuedTileRequests.erase(enqueuedJob);
}
}
void AsyncTileDataProvider::updatePboUsage() {
const bool usingPbo = _pboContainer != nullptr;
const bool shouldUsePbo = _globeBrowsingModule->tileCache()->shouldUsePbo();
// If changed, we need to reset the async tile data provider.
// No need to reset the raw tile data reader when changing PBO usage.
if (usingPbo != shouldUsePbo &&
_resetMode != ResetMode::ShouldResetAllButRawTileDataReader)
{
_resetMode = ResetMode::ShouldResetAllButRawTileDataReader;
LINFO(fmt::format(
"PBO usage updated, prepairing for resetting of tile reader '{}'", _name
));
}
}
void AsyncTileDataProvider::update() {
endUnfinishedJobs();
@@ -210,7 +162,6 @@ void AsyncTileDataProvider::update() {
break;
}
case ResetMode::ShouldNotReset: {
updatePboUsage();
break;
}
default:
@@ -226,7 +177,7 @@ void AsyncTileDataProvider::reset() {
LINFO(fmt::format("Prepairing for resetting of tile reader '{}'", _name));
}
void AsyncTileDataProvider::prepairToBeDeleted() {
void AsyncTileDataProvider::prepareToBeDeleted() {
_resetMode = ResetMode::ShouldBeDeleted;
endEnqueuedJobs();
}
@@ -238,19 +189,6 @@ bool AsyncTileDataProvider::shouldBeDeleted() {
void AsyncTileDataProvider::performReset(ResetRawTileDataReader resetRawTileDataReader) {
ghoul_assert(_enqueuedTileRequests.empty(), "No enqueued requests left");
// Re-initialize PBO container
if (_globeBrowsingModule->tileCache()->shouldUsePbo()) {
size_t pboNumBytes = _rawTileDataReader->tileTextureInitData().totalNumBytes();
_pboContainer = std::make_unique<PixelBufferContainer<TileIndex::TileHashKey>>(
pboNumBytes,
PixelBuffer::Usage::StreamDraw,
10
);
}
else {
_pboContainer = nullptr;
}
// Reset raw tile data reader
if (resetRawTileDataReader == ResetRawTileDataReader::Yes) {
_rawTileDataReader->reset();

View File

@@ -25,20 +25,19 @@
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___ASYNC_TILE_DATAPROVIDER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___ASYNC_TILE_DATAPROVIDER___H__
#include <modules/globebrowsing/other/prioritizingconcurrentjobmanager.h>
#include <modules/globebrowsing/tile/tileindex.h>
#include <modules/globebrowsing/src/prioritizingconcurrentjobmanager.h>
#include <modules/globebrowsing/src/rawtiledatareader.h>
#include <modules/globebrowsing/src/tileindex.h>
#include <ghoul/misc/boolean.h>
#include <map>
#include <optional>
#include <set>
namespace openspace { class GlobeBrowsingModule; }
namespace openspace::globebrowsing {
template <typename T> class PixelBufferContainer;
struct RawTile;
class RawTileDataReader;
/**
* The responsibility of this class is to enqueue tile requests and fetching finished
@@ -51,7 +50,7 @@ public:
* tile loading.
*/
AsyncTileDataProvider(std::string name,
std::shared_ptr<RawTileDataReader> rawTileDataReader);
std::unique_ptr<RawTileDataReader> rawTileDataReader);
~AsyncTileDataProvider();
@@ -63,20 +62,20 @@ public:
/**
* Get all finished jobs.
*/
std::vector<std::shared_ptr<RawTile>> rawTiles();
std::vector<RawTile> rawTiles();
/**
* Get one finished job.
*/
std::shared_ptr<RawTile> popFinishedRawTile();
std::optional<RawTile> popFinishedRawTile();
void update();
void reset();
void prepairToBeDeleted();
void prepareToBeDeleted();
bool shouldBeDeleted();
std::shared_ptr<RawTileDataReader> rawTileDataReader() const;
const RawTileDataReader& rawTileDataReader() const;
float noDataValueAsFloat() const;
protected:
@@ -103,21 +102,17 @@ protected:
void endEnqueuedJobs();
void updatePboUsage();
void performReset(ResetRawTileDataReader resetRawTileDataReader);
private:
const std::string _name;
GlobeBrowsingModule* _globeBrowsingModule;
/// The reader used for asynchronous reading
std::shared_ptr<RawTileDataReader> _rawTileDataReader;
std::unique_ptr<RawTileDataReader> _rawTileDataReader;
PrioritizingConcurrentJobManager<RawTile, TileIndex::TileHashKey>
_concurrentJobManager;
/// nullptr if pbo is not used for texture uploading. Otherwise initialized.
std::unique_ptr<PixelBufferContainer<TileIndex::TileHashKey>> _pboContainer;
std::set<TileIndex::TileHashKey> _enqueuedTileRequests;
ResetMode _resetMode = ResetMode::ShouldResetAllButRawTileDataReader;

View File

@@ -22,27 +22,95 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___TILE___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILE___H__
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING__BASICTYPES___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING__BASICTYPES___H__
#include <modules/globebrowsing/tile/tilemetadata.h>
#include <ghoul/glm.h>
#include <memory>
#include <optional>
#include <vector>
namespace ghoul::opengl { class Texture; }
namespace openspace::globebrowsing {
struct TileUvTransform;
struct AABB3 {
glm::vec3 min = glm::vec3(std::numeric_limits<float>::max());
glm::vec3 max = glm::vec3(-std::numeric_limits<float>::max());
};
struct Geodetic2 {
double lat;
double lon;
};
struct Geodetic3 {
Geodetic2 geodetic2;
double height;
};
struct PixelRegion {
glm::ivec2 start = glm::ivec2(0);
glm::ivec2 numPixels = glm::ivec2(0);
};
struct IODescription {
struct ReadData {
int overview;
PixelRegion region;
PixelRegion fullRegion;
} read;
struct WriteData {
PixelRegion region;
size_t bytesPerLine;
size_t totalNumBytes;
} write;
};
enum Quad {
NORTH_WEST = 0,
NORTH_EAST,
SOUTH_WEST,
SOUTH_EAST
};
struct TileDepthTransform {
float scale;
float offset;
};
struct TileMetaData {
std::vector<float> maxValues;
std::vector<float> minValues;
std::vector<bool> hasMissingData;
};
/**
* Defines a status and may have a Texture and TileMetaData
*/
class Tile {
public:
/**
* Describe if this Tile is good for usage (OK) or otherwise
* the reason why it is not.
*/
/**
* Describe if this Tile is good for usage (OK) or otherwise
* the reason why it is not.
*/
enum class Status {
/**
* E.g when texture data is not currently in memory.
@@ -71,27 +139,30 @@ public:
OK
};
Tile(ghoul::opengl::Texture* texture, std::shared_ptr<TileMetaData> metaData,
Status status);
~Tile() = default;
TileMetaData* metaData() const;
Status status() const;
ghoul::opengl::Texture* texture() const;
/**
* A tile with status unavailable that any user can return to
* indicate that a tile was unavailable.
*/
static const Tile TileUnavailable;
private:
ghoul::opengl::Texture* _texture;
std::shared_ptr<TileMetaData> _metaData;
Status _status;
ghoul::opengl::Texture* texture = nullptr;
std::optional<TileMetaData> metaData = std::nullopt;
Status status = Status::Unavailable;
};
struct TileUvTransform {
glm::vec2 uvOffset;
glm::vec2 uvScale;
};
struct ChunkTile {
Tile tile;
TileUvTransform uvTransform;
TileDepthTransform depthTransform;
};
using ChunkTilePile = std::vector<ChunkTile>;
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILE___H__
#endif // __OPENSPACE_MODULE_GLOBEBROWSING__BASICTYPES___H__

View File

@@ -22,10 +22,10 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/globebrowsing/dashboard/dashboarditemglobelocation.h>
#include <modules/globebrowsing/src/dashboarditemglobelocation.h>
#include <modules/globebrowsing/geometry/geodetic2.h>
#include <modules/globebrowsing/globes/renderableglobe.h>
#include <modules/globebrowsing/src/basictypes.h>
#include <modules/globebrowsing/src/renderableglobe.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <openspace/engine/globals.h>
@@ -115,7 +115,7 @@ DashboardItemGlobeLocation::DashboardItemGlobeLocation(
const ghoul::Dictionary& dictionary)
: DashboardItem(dictionary)
, _fontName(FontNameInfo, KeyFontMono)
, _fontSize(FontSizeInfo, DefaultFontSize, 6.f, 144.f, 1.f)
, _fontSize(FontSizeInfo, DefaultFontSize, 10.f, 144.f, 1.f)
, _font(global::fontManager.font(KeyFontMono, 10))
{
documentation::testSpecificationAndThrow(
@@ -148,14 +148,13 @@ void DashboardItemGlobeLocation::render(glm::vec2& penPosition) {
using namespace globebrowsing;
SceneGraphNode* n = global::navigationHandler.focusNode();
const RenderableGlobe* globe = dynamic_cast<const RenderableGlobe*>(n->renderable());
const RenderableGlobe* globe = dynamic_cast<const RenderableGlobe*>(n->renderable());
if (!globe) {
return;
}
const glm::dvec3 cameraPosition = global::navigationHandler.camera()->positionVec3();
const glm::dmat4 inverseModelTransform =
global::navigationHandler.focusNode()->inverseModelTransform();
const glm::dmat4 inverseModelTransform = n->inverseModelTransform();
const glm::dvec3 cameraPositionModelSpace =
glm::dvec3(inverseModelTransform * glm::dvec4(cameraPosition, 1.0));
const SurfacePositionHandle posHandle = globe->calculateSurfacePositionHandle(
@@ -175,8 +174,9 @@ void DashboardItemGlobeLocation::render(glm::vec2& penPosition) {
bool isEast = lon > 0.0;
lon = std::abs(lon);
const double altitude = glm::length(cameraPositionModelSpace -
posHandle.centerToReferenceSurface);
const double altitude = glm::length(
cameraPositionModelSpace - posHandle.centerToReferenceSurface
);
std::pair<double, std::string> dist = simplifyDistance(altitude);
penPosition.y -= _font->height();
@@ -187,7 +187,8 @@ void DashboardItemGlobeLocation::render(glm::vec2& penPosition) {
"Position: {:03.2f}{}, {:03.2f}{} Altitude: {} {}",
lat, isNorth ? "N" : "S",
lon, isEast ? "E" : "W",
dist.first, dist.second)
dist.first, dist.second
)
);
}
glm::vec2 DashboardItemGlobeLocation::size() const {

View File

@@ -22,18 +22,16 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/globebrowsing/geometry/ellipsoid.h>
#include <modules/globebrowsing/geometry/geodetic2.h>
#include <modules/globebrowsing/geometry/geodetic3.h>
#include <modules/globebrowsing/src/ellipsoid.h>
#include <modules/globebrowsing/src/basictypes.h>
#include <algorithm>
#include <array>
#include <vector>
namespace {
constexpr const size_t MaxIterations = 8;
}
} // namespace
namespace openspace::globebrowsing {
@@ -42,30 +40,25 @@ Ellipsoid::Ellipsoid(glm::dvec3 radii) : _radii(radii) {
}
void Ellipsoid::updateInternalCache() {
_cached._radiiSquared = glm::dvec3(
_radii.x * _radii.x,
_radii.y * _radii.y,
_radii.z * _radii.z
);
_cached.radiiSquared = _radii * _radii;
_cached._oneOverRadiiSquared = glm::dvec3(1.0) / _cached._radiiSquared;
_cached._radiiToTheFourth = _cached._radiiSquared * _cached._radiiSquared;
_cached.oneOverRadiiSquared = glm::dvec3(1.0) / _cached.radiiSquared;
_cached.radiiToTheFourth = _cached.radiiSquared * _cached.radiiSquared;
std::array<double, 3> radii = { _radii.x, _radii.y, _radii.z };
std::sort(radii.begin(), radii.end());
_cached._minimumRadius = radii[0];
_cached._medianRadius = radii[1];
_cached._maximumRadius = radii[2];
_cached.minimumRadius = radii[0];
_cached.maximumRadius = radii[2];
}
glm::dvec3 Ellipsoid::geocentricSurfaceProjection(const glm::dvec3& p) const {
const double beta = 1.0 / sqrt(dot(p * p, _cached._oneOverRadiiSquared));
const double beta = 1.0 / sqrt(dot(p * p, _cached.oneOverRadiiSquared));
return beta * p;
}
glm::dvec3 Ellipsoid::geodeticSurfaceProjection(const glm::dvec3& p) const {
const double beta = 1.0 / sqrt(dot(p * p, _cached._oneOverRadiiSquared));
const double n = glm::length(beta * p * _cached._oneOverRadiiSquared);
const double beta = 1.0 / sqrt(dot(p * p, _cached.oneOverRadiiSquared));
const double n = glm::length(beta * p * _cached.oneOverRadiiSquared);
double alpha = (1.0 - beta) * (glm::length(p) / n);
const glm::dvec3 p2 = p * p;
@@ -79,13 +72,13 @@ glm::dvec3 Ellipsoid::geodeticSurfaceProjection(const glm::dvec3& p) const {
do {
alpha -= (s / dSdA);
d = glm::dvec3(1.0) + alpha * _cached._oneOverRadiiSquared;
d = glm::dvec3(1.0) + alpha * _cached.oneOverRadiiSquared;
const glm::dvec3 d2 = d * d;
const glm::dvec3 d3 = d * d2;
s = glm::dot(p2 / (_cached._radiiSquared * d2), glm::dvec3(1.0)) - 1.0;
s = glm::dot(p2 / (_cached.radiiSquared * d2), glm::dvec3(1.0)) - 1.0;
dSdA = -2.0 * glm::dot(p2 / (_cached._radiiToTheFourth * d3), glm::dvec3(1.0));
dSdA = -2.0 * glm::dot(p2 / (_cached.radiiToTheFourth * d3), glm::dvec3(1.0));
++nIterations;
}
while (std::abs(s) > epsilon && nIterations < MaxIterations);
@@ -96,7 +89,7 @@ glm::dvec3 Ellipsoid::geodeticSurfaceProjection(const glm::dvec3& p) const {
glm::dvec3 Ellipsoid::geodeticSurfaceNormalForGeocentricallyProjectedPoint(
const glm::dvec3& p) const
{
const glm::dvec3 normal = p * _cached._oneOverRadiiSquared;
const glm::dvec3 normal = p * _cached.oneOverRadiiSquared;
return glm::normalize(normal);
}
@@ -114,28 +107,12 @@ const glm::dvec3& Ellipsoid::radii() const {
return _radii;
}
const glm::dvec3& Ellipsoid::radiiSquared() const {
return _cached._radiiSquared;
}
const glm::dvec3& Ellipsoid::oneOverRadiiSquared() const {
return _cached._oneOverRadiiSquared;
}
const glm::dvec3& Ellipsoid::radiiToTheFourth() const {
return _cached._radiiToTheFourth;
}
double Ellipsoid::minimumRadius() const {
return _cached._minimumRadius;
return _cached.minimumRadius;
}
double Ellipsoid::maximumRadius() const {
return _cached._maximumRadius;
}
double Ellipsoid::averageRadius() const {
return (_radii.x + _radii.y + _radii.z) / 3.0;
return _cached.maximumRadius;
}
double Ellipsoid::longitudalDistance(double lat, double lon1, double lon2) const {
@@ -155,7 +132,10 @@ double Ellipsoid::greatCircleDistance(const Geodetic2& p1, const Geodetic2& p2)
glm::length(glm::cross(n1, n2)) / glm::dot(n1, n2)
);
const Geodetic2 pMid = (p1 + p2) / 2;
const Geodetic2 pMid = {
(p1.lat + p2.lat) / 2.0,
(p1.lon + p2.lon) / 2.0
};
const glm::dvec3 centralNormal = cartesianSurfacePosition(pMid);
return centralAngle * glm::length(centralNormal);
@@ -163,10 +143,10 @@ double Ellipsoid::greatCircleDistance(const Geodetic2& p1, const Geodetic2& p2)
Geodetic2 Ellipsoid::cartesianToGeodetic2(const glm::dvec3& p) const {
const glm::dvec3 normal = geodeticSurfaceNormalForGeocentricallyProjectedPoint(p);
return Geodetic2(
asin(normal.z / length(normal)), // Latitude
atan2(normal.y, normal.x) // Longitude
);
Geodetic2 res;
res.lat = asin(normal.z / length(normal));
res.lon = atan2(normal.y, normal.x);
return res;
}
glm::dvec3 Ellipsoid::cartesianSurfacePosition(const Geodetic2& geodetic2) const {
@@ -176,24 +156,22 @@ glm::dvec3 Ellipsoid::cartesianSurfacePosition(const Geodetic2& geodetic2) const
glm::dvec3 Ellipsoid::cartesianPosition(const Geodetic3& geodetic3) const {
const glm::dvec3 normal = geodeticSurfaceNormal(geodetic3.geodetic2);
const glm::dvec3 k = _cached._radiiSquared * normal;
const glm::dvec3 k = _cached.radiiSquared * normal;
const double gamma = sqrt(dot(k, normal));
const glm::dvec3 rSurface = k / gamma;
return rSurface + geodetic3.height * normal;
}
void Ellipsoid::setShadowConfigurationArray(
const std::vector<Ellipsoid::ShadowConfiguration>& shadowConfArray)
std::vector<Ellipsoid::ShadowConfiguration> shadowConfArray)
{
_shadowConfArray = shadowConfArray;
_shadowConfArray = std::move(shadowConfArray);
}
std::vector<Ellipsoid::ShadowConfiguration> Ellipsoid::shadowConfigurationArray() const {
const std::vector<Ellipsoid::ShadowConfiguration>&
Ellipsoid::shadowConfigurationArray() const
{
return _shadowConfArray;
}
bool Ellipsoid::hasEclipseShadows() const {
return !_shadowConfArray.empty();
}
} // namespace openspace::globebrowsing

View File

@@ -77,13 +77,9 @@ public:
glm::dvec3 geodeticSurfaceNormal(const Geodetic2& geodetic2) const;
const glm::dvec3& radii() const;
const glm::dvec3& radiiSquared() const;
const glm::dvec3& oneOverRadiiSquared() const;
const glm::dvec3& radiiToTheFourth() const;
double minimumRadius() const;
double maximumRadius() const;
double averageRadius() const;
double longitudalDistance(double lat, double lon1, double lon2) const;
double greatCircleDistance(const Geodetic2& p1, const Geodetic2& p2) const;
@@ -93,19 +89,17 @@ public:
glm::dvec3 cartesianPosition(const Geodetic3& geodetic3) const;
void setShadowConfigurationArray(
const std::vector<Ellipsoid::ShadowConfiguration>& shadowConfArray
std::vector<Ellipsoid::ShadowConfiguration> shadowConfArray
);
std::vector<Ellipsoid::ShadowConfiguration> shadowConfigurationArray() const;
bool hasEclipseShadows() const;
const std::vector<Ellipsoid::ShadowConfiguration>& shadowConfigurationArray() const;
private:
struct EllipsoidCache {
glm::dvec3 _radiiSquared;
glm::dvec3 _oneOverRadiiSquared;
glm::dvec3 _radiiToTheFourth;
double _minimumRadius;
double _maximumRadius;
double _medianRadius;
glm::dvec3 radiiSquared;
glm::dvec3 oneOverRadiiSquared;
glm::dvec3 radiiToTheFourth;
double minimumRadius;
double maximumRadius;
} _cached;
void updateInternalCache();

View File

@@ -22,20 +22,16 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifdef GLOBEBROWSING_USE_GDAL
#include <modules/globebrowsing/tile/rawtiledatareader/gdalwrapper.h>
#include <modules/globebrowsing/src/gdalwrapper.h>
#include <openspace/engine/configuration.h>
#include <openspace/engine/globals.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/ghoul.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/consolelog.h>
#include <ghoul/logging/logmanager.h>
#include <gdal.h>
#include <cpl_conv.h>
#include <gdal.h>
namespace {
constexpr const char* _loggerCat = "GdalWrapper";
@@ -53,22 +49,25 @@ namespace {
"This function sets the maximum amount of RAM memory in MB that GDAL is "
"permitted to use for caching."
};
void gdalErrorHandler(CPLErr eErrClass, int, const char* msg) {
// No need to try to do this check earlier and only install this method as an error
// handler if the logging is desired as the default behavior of GDAL is to log errors
// to stderr.
if (openspace::globebrowsing::GdalWrapper::ref().logGdalErrors()) {
switch (eErrClass) {
case CE_None: break;
case CE_Debug: LDEBUGC("GDAL", msg); break;
case CE_Warning: LWARNINGC("GDAL", msg); break;
case CE_Failure: LERRORC("GDAL", msg); break;
case CE_Fatal: LFATALC("GDAL", msg); break;
}
}
}
} // namespace
namespace openspace::globebrowsing {
void gdalErrorHandler(CPLErr eErrClass, int, const char* msg) {
if (GdalWrapper::ref().logGdalErrors()) {
switch (eErrClass) {
case CE_None: break;
case CE_Debug: LDEBUGC ("GDAL", msg); break;
case CE_Warning: LWARNINGC("GDAL", msg); break;
case CE_Failure: LERRORC ("GDAL", msg); break;
case CE_Fatal: LFATALC ("GDAL", msg); break;
}
}
}
GdalWrapper* GdalWrapper::_singleton = nullptr;
void GdalWrapper::create(size_t maximumCacheSize, size_t maximumMaximumCacheSize) {
@@ -85,11 +84,11 @@ GdalWrapper& GdalWrapper::ref() {
return *_singleton;
}
size_t GDALCacheUsed() {
int64_t GDALCacheUsed() {
return GDALGetCacheUsed64();
}
size_t GDALMaximumCacheSize() {
int64_t GDALMaximumCacheSize() {
return GDALGetCacheMax64();
}
@@ -100,7 +99,7 @@ bool GdalWrapper::logGdalErrors() const {
GdalWrapper::GdalWrapper(size_t maximumCacheSize, size_t maximumMaximumCacheSize)
: PropertyOwner({ "GdalWrapper" })
, _logGdalErrors(LogGdalErrorInfo, false)
, _gdalMaximumCacheSize (
, _gdalMaximumCacheSize(
GdalMaximumCacheInfo,
static_cast<int>(maximumCacheSize / (1024ULL * 1024ULL)), // Default
0, // Minimum: No caching
@@ -124,8 +123,7 @@ GdalWrapper::GdalWrapper(size_t maximumCacheSize, size_t maximumMaximumCacheSize
_gdalMaximumCacheSize.onChange([&] {
// MB to Bytes
GDALSetCacheMax64(
static_cast<size_t>(_gdalMaximumCacheSize) *
1024ULL * 1024ULL
static_cast<int64_t>(_gdalMaximumCacheSize) * 1024ULL * 1024ULL
);
});
}
@@ -158,5 +156,3 @@ void GdalWrapper::setGdalProxyConfiguration() {
}
} // namespace openspace::globebrowsing
#endif // GLOBEBROWSING_USE_GDAL

View File

@@ -25,8 +25,6 @@
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___GDAL_WRAPPER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___GDAL_WRAPPER___H__
#ifdef GLOBEBROWSING_USE_GDAL
#include <openspace/properties/propertyowner.h>
#include <openspace/properties/scalar/boolproperty.h>
@@ -36,11 +34,6 @@
namespace openspace::globebrowsing {
/**
* Function for passing GDAL error messages to the GHOUL logging system.
*/
void gdalErrorHandler(CPLErr eErrClass, int errNo, const char* msg);
/**
* Singleton class interfacing with global GDAL functions.
*/
@@ -62,13 +55,13 @@ public:
* Get the current size of the GDAL in memory cache.
* \returns the number of bytes currently in the GDAL memory cache.
*/
static size_t GDALCacheUsed();
static int64_t GDALCacheUsed();
/**
* Get the maximum GDAL in memory cache size.
* \returns the maximum number of bytes allowed for the GDAL cache.
*/
static size_t GDALMaximumCacheSize();
static int64_t GDALMaximumCacheSize();
bool logGdalErrors() const;
@@ -86,6 +79,4 @@ private:
} // namespace openspace::globebrowsing
#endif // GLOBEBROWSING_USE_GDAL
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___GDAL_WRAPPER___H__

Some files were not shown because too many files have changed in this diff Show More