mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-03-13 08:58:54 -05:00
Solve merge conflict
This commit is contained in:
@@ -6,34 +6,29 @@ return {
|
||||
Renderable = {
|
||||
Type = "RenderableGlobe",
|
||||
Radii = {6378137.0, 6378137.0, 6356752.314245}, -- Earth's radii
|
||||
SegmentsPerPatch = 64,
|
||||
Textures = {
|
||||
ColorTextures = {
|
||||
{
|
||||
Name = "ESRI Imagery World 2D",
|
||||
FilePath = "map_service_configs/ESRI_Imagery_World_2D.wms",
|
||||
},
|
||||
|
||||
|
||||
--[[
|
||||
{
|
||||
Name = "Coastlines",
|
||||
FilePath = "map_service_configs/Coastlines.xml",
|
||||
},
|
||||
{
|
||||
Name = "VIIRS_SNPP_CorrectedReflectance_TrueColor",
|
||||
FilePath = "map_service_configs/VIIRS_SNPP_CorrectedReflectance_TrueColor.xml"
|
||||
},
|
||||
{
|
||||
Name = "MODIS_Terra_CorrectedReflectance_TrueColor",
|
||||
FilePath = "map_service_configs/MODIS_Terra_CorrectedReflectance_TrueColor.xml"
|
||||
},
|
||||
{
|
||||
Name = "MODIS_Water_Mask",
|
||||
FilePath = "map_service_configs/MODIS_Water_Mask.xml"
|
||||
},
|
||||
{
|
||||
Name = "Coastlines",
|
||||
FilePath = "map_service_configs/Coastlines.xml",
|
||||
},
|
||||
{
|
||||
Name = "ESRI Imagery World 2D",
|
||||
FilePath = "map_service_configs/ESRI_Imagery_World_2D.wms",
|
||||
},
|
||||
|
||||
{
|
||||
Name = "MODIS_Terra_CorrectedReflectance_TrueColor",
|
||||
FilePath = "map_service_configs/MODIS_Terra_CorrectedReflectance_TrueColor.xml",
|
||||
},
|
||||
|
||||
--]]
|
||||
},
|
||||
HeightMaps = {
|
||||
{
|
||||
|
||||
Submodule ext/ghoul updated: 5c9f358af8...f3420c0b5c
@@ -34,6 +34,8 @@
|
||||
#include <openspace/util/keys.h>
|
||||
|
||||
#include <list>
|
||||
#include <modules/globebrowsing/globes/renderableglobe.h>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace openspace {
|
||||
@@ -189,7 +191,7 @@ public:
|
||||
~InteractionMode();
|
||||
|
||||
// Mutators
|
||||
void setFocusNode(SceneGraphNode* focusNode);
|
||||
virtual void setFocusNode(SceneGraphNode* focusNode);
|
||||
void setCamera(Camera* camera);
|
||||
|
||||
// Accessors
|
||||
@@ -256,7 +258,7 @@ public:
|
||||
~OrbitalInteractionMode();
|
||||
|
||||
virtual void update(double deltaTime);
|
||||
private:
|
||||
protected:
|
||||
void updateMouseStatesFromInput(double deltaTime);
|
||||
void updateCameraStateFromMouseStates();
|
||||
|
||||
@@ -271,6 +273,22 @@ private:
|
||||
glm::dquat _globalCameraRotation;
|
||||
};
|
||||
|
||||
class GlobeBrowsingInteractionMode : public OrbitalInteractionMode
|
||||
{
|
||||
public:
|
||||
GlobeBrowsingInteractionMode(
|
||||
std::shared_ptr<InputState> inputState,
|
||||
double sensitivity,
|
||||
double velocityScaleFactor);
|
||||
~GlobeBrowsingInteractionMode();
|
||||
|
||||
virtual void setFocusNode(SceneGraphNode* focusNode);
|
||||
virtual void update(double deltaTime);
|
||||
private:
|
||||
void updateCameraStateFromMouseStates();
|
||||
RenderableGlobe* _globe;
|
||||
};
|
||||
|
||||
|
||||
class InteractionHandler : public properties::PropertyOwner
|
||||
{
|
||||
|
||||
@@ -73,9 +73,9 @@ namespace openspace {
|
||||
// now working with float precision. To be changed to double later.
|
||||
// The reason double does not work yet is because of the setUniform function
|
||||
// in ghoul::opengl
|
||||
typedef glm::quat Quat;
|
||||
typedef glm::mat4 Mat4;
|
||||
typedef glm::vec3 Vec3;
|
||||
typedef glm::dquat Quat;
|
||||
typedef glm::dmat4 Mat4;
|
||||
typedef glm::dvec3 Vec3;
|
||||
|
||||
// Static constants
|
||||
static const Vec3 _VIEW_DIRECTION_CAMERA_SPACE;
|
||||
@@ -113,6 +113,8 @@ namespace openspace {
|
||||
// @TODO this should simply be called viewMatrix!
|
||||
// Or it needs to be changed so that it actually is combined. Right now it is
|
||||
// only the view matrix that is the same for all SGCT cameras.
|
||||
// Right now this function returns the actual combined matrix which makes some
|
||||
// of the old calls to the function wrong..
|
||||
const Mat4& combinedViewMatrix() const;
|
||||
|
||||
// Synchronization
|
||||
|
||||
@@ -58,6 +58,10 @@ class SyncBuffer;
|
||||
|
||||
class Time {
|
||||
public:
|
||||
Time();
|
||||
Time(const Time& other);
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the Time singleton.
|
||||
* \return <code>true</code> if the initialization succeeded, <code>false</code>
|
||||
@@ -123,6 +127,12 @@ public:
|
||||
*/
|
||||
std::string currentTimeUTC() const;
|
||||
|
||||
/**
|
||||
* Returns the current time as a ISO 8601 formatted, i.e YYYY-MM-DDThh:mm:ssZ
|
||||
* \return The current time as a ISO 8601 formatted string
|
||||
*/
|
||||
std::string ISO8601() const;
|
||||
|
||||
/**
|
||||
* Sets the delta time value that is the number of seconds that should pass for each
|
||||
* real-time second. This value is used in the advanceTime(double) method to easily
|
||||
|
||||
@@ -28,8 +28,6 @@ set(HEADER_FILES
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globes/renderableglobe.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globes/globemesh.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globes/clipmapglobe.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globes/clipmappyramid.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globes/chunkedlodglobe.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globes/chunknode.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globes/chunkindex.h
|
||||
@@ -38,7 +36,7 @@ set(HEADER_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/meshes/trianglesoup.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/meshes/grid.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/meshes/basicgrid.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/meshes/clipmapgrid.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/meshes/skirtedgrid.h
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/geodetics/geodetic2.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/geodetics/angle.h
|
||||
@@ -49,9 +47,10 @@ set(HEADER_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/aabb.h
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/other/distanceswitch.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/other/patchcoverageprovider.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/other/temporaltileprovider.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/other/tileprovider.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/other/texturedataprovider.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/other/tiledataset.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/other/asynctilereader.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/other/lrucache.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/other/concurrentjobmanager.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/other/threadpool.h
|
||||
@@ -64,8 +63,6 @@ set(HEADER_FILES
|
||||
set(SOURCE_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globes/renderableglobe.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globes/globemesh.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globes/clipmapglobe.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globes/clipmappyramid.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globes/chunkedlodglobe.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globes/chunknode.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globes/chunkindex.cpp
|
||||
@@ -74,7 +71,7 @@ set(SOURCE_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/meshes/trianglesoup.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/meshes/grid.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/meshes/basicgrid.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/meshes/clipmapgrid.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/meshes/skirtedgrid.cpp
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/geodetics/geodetic2.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/geodetics/angle.inl
|
||||
@@ -85,9 +82,10 @@ set(SOURCE_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/aabb.cpp
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/other/distanceswitch.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/other/patchcoverageprovider.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/other/temporaltileprovider.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/other/tileprovider.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/other/texturedataprovider.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/other/tiledataset.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/other/asynctilereader.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/other/lrucache.inl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/other/concurrentjobmanager.inl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/other/threadpool.cpp
|
||||
@@ -103,11 +101,6 @@ set(SHADER_FILES
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/globalchunkedlodpatch_vs.glsl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/globalchunkedlodpatch_fs.glsl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/globalclipmappatch_vs.glsl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/globalclipmappatch_fs.glsl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/localclipmappatch_vs.glsl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/simple_vs.glsl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/simple_fs.glsl
|
||||
)
|
||||
|
||||
source_group("Shader Files" FILES ${SHADER_FILES})
|
||||
|
||||
@@ -121,7 +121,7 @@ namespace openspace {
|
||||
|
||||
Scalar scaleFactor = _owner->lodScaleFactor * ellipsoid.minimumRadius();;
|
||||
Scalar projectedScaleFactor = scaleFactor / distance;
|
||||
int desiredLevel = floor(log2(projectedScaleFactor));
|
||||
int desiredLevel = ceil(log2(projectedScaleFactor));
|
||||
|
||||
// clamp level
|
||||
desiredLevel = glm::clamp(desiredLevel, _owner->minSplitDepth, _owner->maxSplitDepth);
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
#include <modules/globebrowsing/globes/chunkedlodglobe.h>
|
||||
|
||||
#include <modules/globebrowsing/meshes/basicgrid.h>
|
||||
#include <modules/globebrowsing/meshes/skirtedgrid.h>
|
||||
|
||||
// open space includes
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
@@ -53,6 +53,7 @@ namespace openspace {
|
||||
|
||||
ChunkedLodGlobe::ChunkedLodGlobe(
|
||||
const Ellipsoid& ellipsoid,
|
||||
size_t segmentsPerPatch,
|
||||
std::shared_ptr<TileProviderManager> tileProviderManager)
|
||||
: _ellipsoid(ellipsoid)
|
||||
, _leftRoot(new ChunkNode(Chunk(this, LEFT_HEMISPHERE_INDEX)))
|
||||
@@ -62,9 +63,9 @@ namespace openspace {
|
||||
, _savedCamera(nullptr)
|
||||
{
|
||||
|
||||
auto geometry = std::shared_ptr<BasicGrid>(new BasicGrid(
|
||||
64,
|
||||
64,
|
||||
auto geometry = std::shared_ptr<SkirtedGrid>(new SkirtedGrid(
|
||||
segmentsPerPatch,
|
||||
segmentsPerPatch,
|
||||
TriangleSoup::Positions::No,
|
||||
TriangleSoup::TextureCoordinates::Yes,
|
||||
TriangleSoup::Normals::No));
|
||||
|
||||
@@ -56,6 +56,7 @@ namespace openspace {
|
||||
public:
|
||||
ChunkedLodGlobe(
|
||||
const Ellipsoid& ellipsoid,
|
||||
size_t segmentsPerPatch,
|
||||
std::shared_ptr<TileProviderManager> tileProviderManager);
|
||||
virtual ~ChunkedLodGlobe();
|
||||
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2016 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
|
||||
#include <modules/globebrowsing/globes/clipmapglobe.h>
|
||||
|
||||
#include <modules/globebrowsing/meshes/clipmapgrid.h>
|
||||
|
||||
// open space includes
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/util/spicemanager.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
|
||||
// ghoul includes
|
||||
#include <ghoul/misc/assert.h>
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "ClipMapGlobe";
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
ClipMapGlobe::ClipMapGlobe(
|
||||
const Ellipsoid& ellipsoid,
|
||||
std::shared_ptr<TileProviderManager> tileProviderManager)
|
||||
: _clipMapPyramid(Geodetic2(M_PI / 2, M_PI / 2))
|
||||
, _ellipsoid(ellipsoid)
|
||||
{
|
||||
// init Renderer
|
||||
auto outerPatchRenderer = new ClipMapPatchRenderer(
|
||||
shared_ptr<OuterClipMapGrid>(new OuterClipMapGrid(256)),
|
||||
tileProviderManager);
|
||||
_outerPatchRenderer.reset(outerPatchRenderer);
|
||||
auto innerPatchRenderer = new ClipMapPatchRenderer(
|
||||
shared_ptr<InnerClipMapGrid>(new InnerClipMapGrid(256)),
|
||||
tileProviderManager);
|
||||
_innerPatchRenderer.reset(innerPatchRenderer);
|
||||
}
|
||||
|
||||
ClipMapGlobe::~ClipMapGlobe() {
|
||||
}
|
||||
|
||||
const Ellipsoid& ClipMapGlobe::ellipsoid() const
|
||||
{
|
||||
return _ellipsoid;
|
||||
}
|
||||
|
||||
bool ClipMapGlobe::initialize() {
|
||||
return isReady();
|
||||
}
|
||||
|
||||
bool ClipMapGlobe::deinitialize() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClipMapGlobe::isReady() const {
|
||||
bool ready = true;
|
||||
return ready;
|
||||
}
|
||||
|
||||
void ClipMapGlobe::render(const RenderData& data)
|
||||
{
|
||||
int minDepth, maxDepth;
|
||||
calculateDesiredMinAndMaxDepth(data, minDepth, maxDepth);
|
||||
|
||||
// render patches
|
||||
for (size_t i = minDepth; i < maxDepth; i++)
|
||||
{
|
||||
Geodetic2 patchSize = _clipMapPyramid.getPatchSizeAtLevel(i);
|
||||
_outerPatchRenderer->renderPatch(patchSize, data, _ellipsoid);
|
||||
}
|
||||
Geodetic2 patchSize = _clipMapPyramid.getPatchSizeAtLevel(maxDepth);
|
||||
_innerPatchRenderer->renderPatch(patchSize, data, _ellipsoid);
|
||||
}
|
||||
|
||||
void ClipMapGlobe::update(const UpdateData& data) {
|
||||
_innerPatchRenderer->update();
|
||||
_outerPatchRenderer->update();
|
||||
}
|
||||
|
||||
void ClipMapGlobe::calculateDesiredMinAndMaxDepth(
|
||||
const RenderData& data,
|
||||
int& minDepth,
|
||||
int& maxDepth)
|
||||
{
|
||||
Scalar minimumRadius = _ellipsoid.minimumRadius();
|
||||
Vec3 cameraPosition = data.camera.position().dvec3();
|
||||
Vec3 cameraPositionOnSurface = _ellipsoid.geodeticSurfaceProjection(cameraPosition);
|
||||
Scalar h = glm::length(cameraPosition - cameraPositionOnSurface);
|
||||
Scalar cosAngleToHorizon = minimumRadius / (minimumRadius + h);
|
||||
Scalar angleToHorizon = glm::acos(cosAngleToHorizon);
|
||||
Scalar minimumPatchSize = glm::min(
|
||||
_clipMapPyramid.getPatchSizeAtLevel0().lat,
|
||||
_clipMapPyramid.getPatchSizeAtLevel0().lon);
|
||||
minDepth = log2(minimumPatchSize / 2 / angleToHorizon);
|
||||
|
||||
// Calculate desired level based on distance
|
||||
Scalar scaleFactor = 1 * minimumRadius;
|
||||
Scalar projectedScaleFactor = scaleFactor / h;
|
||||
maxDepth = glm::max(static_cast<int>(log2(projectedScaleFactor)), 0);
|
||||
|
||||
// Test smaller and smaller patches until one is outside of frustum
|
||||
int i;
|
||||
for (i = minDepth; i < maxDepth; i++)
|
||||
{
|
||||
Geodetic2 center = _ellipsoid.cartesianToGeodetic2(cameraPosition);
|
||||
Geodetic2 halfSize = _clipMapPyramid.getPatchSizeAtLevel(i) / 2;
|
||||
GeodeticPatch testPatch(center, halfSize);
|
||||
// Do frustrum culling
|
||||
if (FrustumCuller::isVisible(data, testPatch, _ellipsoid)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
maxDepth = i;
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
@@ -1,81 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2016 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __CLIPMAPGLOBE_H__
|
||||
#define __CLIPMAPGLOBE_H__
|
||||
|
||||
// open space includes
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
|
||||
#include <modules/globebrowsing/meshes/trianglesoup.h>
|
||||
#include <modules/globebrowsing/meshes/grid.h>
|
||||
#include <modules/globebrowsing/other/distanceswitch.h>
|
||||
#include <modules/globebrowsing/rendering/patchrenderer.h>
|
||||
#include <modules/globebrowsing/rendering/culling.h>
|
||||
#include <modules/globebrowsing/globes/clipmappyramid.h>
|
||||
#include <modules/globebrowsing/other/TileProviderManager.h>
|
||||
|
||||
namespace ghoul {
|
||||
namespace opengl {
|
||||
class ProgramObject;
|
||||
}
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class ClipMapGlobe : public Renderable {
|
||||
public:
|
||||
ClipMapGlobe(
|
||||
const Ellipsoid& ellipsoid,
|
||||
std::shared_ptr<TileProviderManager> tileProviderManager);
|
||||
~ClipMapGlobe();
|
||||
|
||||
bool initialize() override;
|
||||
bool deinitialize() override;
|
||||
bool isReady() const override;
|
||||
|
||||
void render(const RenderData& data) override;
|
||||
void update(const UpdateData& data) override;
|
||||
|
||||
const Ellipsoid& ellipsoid() const;
|
||||
|
||||
private:
|
||||
void calculateDesiredMinAndMaxDepth(
|
||||
const RenderData& data,
|
||||
int& minDepth,
|
||||
int& maxDepth);
|
||||
|
||||
//shared_ptr<TileProvider> _tileProvider;
|
||||
std::unique_ptr<ClipMapPatchRenderer> _outerPatchRenderer;
|
||||
std::unique_ptr<ClipMapPatchRenderer> _innerPatchRenderer;
|
||||
|
||||
ClipMapPyramid _clipMapPyramid;
|
||||
const Ellipsoid& _ellipsoid;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __CLIPMAPGLOBE_H__
|
||||
@@ -25,7 +25,8 @@
|
||||
#include <modules/globebrowsing/globes/renderableglobe.h>
|
||||
|
||||
#include <modules/globebrowsing/globes/globemesh.h>
|
||||
#include <modules/globebrowsing/globes/clipmapglobe.h>
|
||||
|
||||
#include <modules/globebrowsing/other/threadpool.h>
|
||||
|
||||
// open space includes
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
@@ -41,6 +42,7 @@ namespace {
|
||||
|
||||
// Keys for the dictionary
|
||||
const std::string keyRadii = "Radii";
|
||||
const std::string keySegmentsPerPatch = "SegmentsPerPatch";
|
||||
const std::string keyTextures = "Textures";
|
||||
const std::string keyColorTextures = "ColorTextures";
|
||||
const std::string keyHeightMaps = "HeightMaps";
|
||||
@@ -57,7 +59,7 @@ namespace openspace {
|
||||
, doFrustumCulling(properties::BoolProperty("doFrustumCulling", "doFrustumCulling"))
|
||||
, doHorizonCulling(properties::BoolProperty("doHorizonCulling", "doHorizonCulling"))
|
||||
, mergeInvisible(properties::BoolProperty("mergeInvisible", "mergeInvisible", true))
|
||||
, lodScaleFactor(properties::FloatProperty("lodScaleFactor", "lodScaleFactor", 10.0f, 0.0f, 100.0f))
|
||||
, lodScaleFactor(properties::FloatProperty("lodScaleFactor", "lodScaleFactor", 5.0f, 1.0f, 20.0f))
|
||||
, initChunkVisible(properties::BoolProperty("initChunkVisible", "initChunkVisible", true))
|
||||
, renderSmallChunksFirst(properties::BoolProperty("renderSmallChunksFirst", "renderSmallChunksFirst", true))
|
||||
{
|
||||
@@ -81,7 +83,13 @@ namespace openspace {
|
||||
|
||||
// Read the radii in to its own dictionary
|
||||
Vec3 radii;
|
||||
double patchSegmentsd;
|
||||
|
||||
dictionary.getValue(keyRadii, radii);
|
||||
// Ghoul can't read ints from lua dictionaries
|
||||
dictionary.getValue(keySegmentsPerPatch, patchSegmentsd);
|
||||
int patchSegments = patchSegmentsd;
|
||||
|
||||
_ellipsoid = Ellipsoid(radii);
|
||||
|
||||
|
||||
@@ -94,52 +102,95 @@ namespace openspace {
|
||||
ghoul::Dictionary colorTexturesDictionary;
|
||||
texturesDictionary.getValue(keyColorTextures, colorTexturesDictionary);
|
||||
|
||||
int minimumTextureSide = 1024;
|
||||
int minimumHeightmapSize = 64;
|
||||
int frameUntilFlushRequestQueue = 60;
|
||||
int cacheSize = 5000;
|
||||
|
||||
|
||||
// Create TileProviders for all color textures
|
||||
for (size_t i = 1; i < colorTexturesDictionary.size() + 1; i++)
|
||||
for (size_t i = 0; i < colorTexturesDictionary.size(); i++)
|
||||
{
|
||||
std::string name, path;
|
||||
std::string dictionaryKey = std::to_string(i + 1);
|
||||
ghoul::Dictionary colorTextureDictionary =
|
||||
colorTexturesDictionary.value<ghoul::Dictionary>(std::to_string(i));
|
||||
colorTexturesDictionary.value<ghoul::Dictionary>(dictionaryKey);
|
||||
colorTextureDictionary.getValue("Name", name);
|
||||
colorTextureDictionary.getValue("FilePath", path);
|
||||
std::shared_ptr<TileProvider> colorTextureProvider =
|
||||
std::shared_ptr<TileProvider>(new TileProvider(
|
||||
path, 5000, 1024, 60));
|
||||
_tileProviderManager->addColorTexture(name, colorTextureProvider);
|
||||
|
||||
std::shared_ptr<TileDataset> tileDataset = std::shared_ptr<TileDataset>(
|
||||
new TileDataset(path, minimumTextureSide));
|
||||
|
||||
std::shared_ptr<ThreadPool> threadPool = std::shared_ptr<ThreadPool>(
|
||||
new ThreadPool(1));
|
||||
|
||||
std::shared_ptr<AsyncTileDataProvider> tileReader = std::shared_ptr<AsyncTileDataProvider>(
|
||||
new AsyncTileDataProvider(tileDataset, threadPool));
|
||||
|
||||
std::shared_ptr<TileProvider> colorTextureProvider = std::shared_ptr<TileProvider>(
|
||||
new TileProvider(tileReader, cacheSize, frameUntilFlushRequestQueue));
|
||||
|
||||
_tileProviderManager->addColorTexture(name, colorTextureProvider, true);
|
||||
|
||||
// Create property for this tile provider
|
||||
bool enabled = i == 0; // Only enable first layer
|
||||
_activeColorLayers.push_back(properties::BoolProperty(name, name, enabled));
|
||||
}
|
||||
|
||||
ghoul::Dictionary heightMapsDictionary;
|
||||
texturesDictionary.getValue(keyHeightMaps, heightMapsDictionary);
|
||||
|
||||
// Create TileProviders for all height maps
|
||||
for (size_t i = 1; i < heightMapsDictionary.size() + 1; i++)
|
||||
for (size_t i = 0; i < heightMapsDictionary.size(); i++)
|
||||
{
|
||||
std::string name, path;
|
||||
std::string dictionaryKey = std::to_string(i + 1);
|
||||
ghoul::Dictionary heightMapDictionary =
|
||||
heightMapsDictionary.value<ghoul::Dictionary>(std::to_string(i));
|
||||
heightMapsDictionary.value<ghoul::Dictionary>(dictionaryKey);
|
||||
heightMapDictionary.getValue("Name", name);
|
||||
heightMapDictionary.getValue("FilePath", path);
|
||||
std::shared_ptr<TileProvider> heightMapProvider =
|
||||
std::shared_ptr<TileProvider>(new TileProvider(
|
||||
path, 5000, 64, 60));
|
||||
_tileProviderManager->addHeightMap(name, heightMapProvider);
|
||||
|
||||
std::shared_ptr<TileDataset> tileDataset = std::shared_ptr<TileDataset>(
|
||||
new TileDataset(path, minimumHeightmapSize));
|
||||
|
||||
std::shared_ptr<ThreadPool> threadPool = std::shared_ptr<ThreadPool>(
|
||||
new ThreadPool(1));
|
||||
|
||||
std::shared_ptr<AsyncTileDataProvider> tileReader = std::shared_ptr<AsyncTileDataProvider>(
|
||||
new AsyncTileDataProvider(tileDataset, threadPool));
|
||||
|
||||
std::shared_ptr<TileProvider> heightMapProvider = std::shared_ptr<TileProvider>(
|
||||
new TileProvider(tileReader, cacheSize, frameUntilFlushRequestQueue));
|
||||
|
||||
|
||||
_tileProviderManager->addHeightMap(name, heightMapProvider, true);
|
||||
|
||||
// Create property for this tile provider
|
||||
bool enabled = i == 0; // Only enable first layer
|
||||
_activeHeightMapLayers.push_back(properties::BoolProperty(name, name, enabled));
|
||||
}
|
||||
|
||||
// Add properties for the tile providers
|
||||
for (auto it = _activeColorLayers.begin(); it != _activeColorLayers.end(); it++) {
|
||||
addProperty(*it);
|
||||
}
|
||||
for (auto it = _activeHeightMapLayers.begin(); it != _activeHeightMapLayers.end(); it++) {
|
||||
addProperty(*it);
|
||||
}
|
||||
|
||||
//addSwitchValue(std::shared_ptr<ClipMapGlobe>(
|
||||
// new ClipMapGlobe(_ellipsoid, _tileProviderManager)), 1e8);
|
||||
|
||||
_chunkedLodGlobe = std::shared_ptr<ChunkedLodGlobe>(
|
||||
new ChunkedLodGlobe(_ellipsoid, _tileProviderManager));
|
||||
new ChunkedLodGlobe(_ellipsoid, patchSegments, _tileProviderManager));
|
||||
|
||||
_distanceSwitch.addSwitchValue(_chunkedLodGlobe, 1e9);
|
||||
//_distanceSwitch.addSwitchValue(std::shared_ptr<GlobeMesh>(new GlobeMesh()), 1e10);
|
||||
_distanceSwitch.addSwitchValue(_chunkedLodGlobe, 1e12);
|
||||
}
|
||||
|
||||
RenderableGlobe::~RenderableGlobe() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool RenderableGlobe::initialize() {
|
||||
return _distanceSwitch.initialize();
|
||||
}
|
||||
@@ -165,17 +216,36 @@ namespace openspace {
|
||||
_chunkedLodGlobe->setSaveCamera(nullptr);
|
||||
}
|
||||
}
|
||||
_chunkedLodGlobe->doFrustumCulling = doFrustumCulling.value();
|
||||
_chunkedLodGlobe->doHorizonCulling = doHorizonCulling.value();
|
||||
_chunkedLodGlobe->mergeInvisible = mergeInvisible.value();
|
||||
_chunkedLodGlobe->lodScaleFactor= lodScaleFactor.value();
|
||||
_chunkedLodGlobe->initChunkVisible = initChunkVisible.value();
|
||||
|
||||
_distanceSwitch.render(data);
|
||||
}
|
||||
|
||||
void RenderableGlobe::update(const UpdateData& data) {
|
||||
_time = data.time;
|
||||
_distanceSwitch.update(data);
|
||||
|
||||
_chunkedLodGlobe->doFrustumCulling = doFrustumCulling.value();
|
||||
_chunkedLodGlobe->doHorizonCulling = doHorizonCulling.value();
|
||||
_chunkedLodGlobe->mergeInvisible = mergeInvisible.value();
|
||||
_chunkedLodGlobe->lodScaleFactor = lodScaleFactor.value();
|
||||
_chunkedLodGlobe->initChunkVisible = initChunkVisible.value();
|
||||
|
||||
std::vector<TileProviderManager::TileProviderWithName>& colorTextureProviders =
|
||||
_tileProviderManager->colorTextureProviders();
|
||||
std::vector<TileProviderManager::TileProviderWithName>& heightMapProviders =
|
||||
_tileProviderManager->heightMapProviders();
|
||||
|
||||
for (size_t i = 0; i < colorTextureProviders.size(); i++) {
|
||||
colorTextureProviders[i].isActive = _activeColorLayers[i].value();
|
||||
}
|
||||
for (size_t i = 0; i < heightMapProviders.size(); i++) {
|
||||
heightMapProviders[i].isActive = _activeHeightMapLayers[i].value();
|
||||
}
|
||||
}
|
||||
|
||||
glm::dvec3 RenderableGlobe::geodeticSurfaceProjection(glm::dvec3 position) {
|
||||
return _ellipsoid.geodeticSurfaceProjection(position);
|
||||
}
|
||||
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -64,6 +64,8 @@ public:
|
||||
void render(const RenderData& data) override;
|
||||
void update(const UpdateData& data) override;
|
||||
|
||||
glm::dvec3 geodeticSurfaceProjection(glm::dvec3 position);
|
||||
|
||||
properties::BoolProperty doFrustumCulling;
|
||||
properties::BoolProperty doHorizonCulling;
|
||||
properties::BoolProperty mergeInvisible;
|
||||
@@ -86,6 +88,9 @@ private:
|
||||
|
||||
properties::BoolProperty _saveOrThrowCamera;
|
||||
|
||||
std::vector<properties::BoolProperty> _activeColorLayers;
|
||||
std::vector<properties::BoolProperty> _activeHeightMapLayers;
|
||||
|
||||
DistanceSwitch _distanceSwitch;
|
||||
};
|
||||
|
||||
|
||||
174
modules/globebrowsing/meshes/skirtedgrid.cpp
Normal file
174
modules/globebrowsing/meshes/skirtedgrid.cpp
Normal file
@@ -0,0 +1,174 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2016 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/globebrowsing/meshes/skirtedgrid.h>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "SkirtedGrid";
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
|
||||
SkirtedGrid::SkirtedGrid(
|
||||
unsigned int xSegments,
|
||||
unsigned int ySegments,
|
||||
TriangleSoup::Positions usePositions,
|
||||
TriangleSoup::TextureCoordinates useTextureCoordinates,
|
||||
TriangleSoup::Normals useNormals)
|
||||
: Grid(
|
||||
xSegments,
|
||||
ySegments,
|
||||
usePositions,
|
||||
useTextureCoordinates,
|
||||
useNormals)
|
||||
{
|
||||
_geometry = std::unique_ptr<TriangleSoup>(new TriangleSoup(
|
||||
CreateElements(xSegments, ySegments),
|
||||
usePositions,
|
||||
useTextureCoordinates,
|
||||
useNormals));
|
||||
|
||||
if (usePositions == TriangleSoup::Positions::Yes) {
|
||||
_geometry->setVertexPositions(CreatePositions(_xSegments, _ySegments));
|
||||
}
|
||||
if (useTextureCoordinates == TriangleSoup::TextureCoordinates::Yes) {
|
||||
_geometry->setVertexTextureCoordinates(CreateTextureCoordinates(_xSegments, _ySegments));
|
||||
}
|
||||
if (useNormals == TriangleSoup::Normals::Yes) {
|
||||
_geometry->setVertexNormals(CreateNormals(_xSegments, _ySegments));
|
||||
}
|
||||
}
|
||||
|
||||
SkirtedGrid::~SkirtedGrid()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int SkirtedGrid::xSegments() const {
|
||||
return _xSegments;
|
||||
}
|
||||
|
||||
int SkirtedGrid::ySegments() const {
|
||||
return _ySegments;
|
||||
}
|
||||
|
||||
void SkirtedGrid::validate(int xSegments, int ySegments) {
|
||||
ghoul_assert(xSegments > 0 && ySegments > 0,
|
||||
"Resolution must be at least 1x1. (" << xSegments << ", " << ySegments << ")");
|
||||
}
|
||||
|
||||
inline size_t SkirtedGrid::numElements(int xSegments, int ySegments) {
|
||||
return 3 * 2 * xSegments * ySegments;
|
||||
}
|
||||
|
||||
inline size_t SkirtedGrid::numVertices(int xSegments, int ySegments) {
|
||||
return (xSegments + 1) * (ySegments + 1);
|
||||
}
|
||||
|
||||
std::vector<GLuint> SkirtedGrid::CreateElements(int xSegments, int ySegments) {
|
||||
validate(xSegments, ySegments);
|
||||
|
||||
std::vector<GLuint> elements;
|
||||
elements.reserve(numElements(xSegments + 2, ySegments + 2));
|
||||
for (unsigned int y = 0; y < ySegments + 2; y++) {
|
||||
for (unsigned int x = 0; x < xSegments + 2; x++) {
|
||||
|
||||
// x v01---v11 x ..
|
||||
// | / |
|
||||
// x v00---v10 x ..
|
||||
//
|
||||
// x x x x ..
|
||||
// : : : :
|
||||
|
||||
GLuint v00 = (y + 0) * (xSegments + 2 + 1) + x + 0;
|
||||
GLuint v10 = (y + 0) * (xSegments + 2 + 1) + x + 1;
|
||||
GLuint v01 = (y + 1) * (xSegments + 2 + 1) + x + 0;
|
||||
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);
|
||||
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 (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> 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.push_back(glm::vec2(
|
||||
glm::clamp(static_cast<float>(x) / static_cast<float>(xSegments), 0 - 1.0f / (2 * xSegments), 1 + 1.0f / (2 * xSegments)),
|
||||
glm::clamp(static_cast<float>(y) / static_cast<float>(ySegments), 0 - 1.0f / (2 * ySegments), 1 + 1.0f / (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.push_back(glm::vec3(0, 0, 1));
|
||||
}
|
||||
}
|
||||
|
||||
return normals;
|
||||
}
|
||||
}// namespace openspace
|
||||
@@ -23,37 +23,52 @@
|
||||
****************************************************************************************/
|
||||
|
||||
|
||||
#ifndef __SKIRTEDGRID_H__
|
||||
#define __SKIRTEDGRID_H__
|
||||
|
||||
#include <modules/globebrowsing/globes/clipmappyramid.h>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
#include <modules/globebrowsing/meshes/basicgrid.h>
|
||||
|
||||
// ghoul includes
|
||||
#include <ghoul/misc/assert.h>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "ClipMapPyramid";
|
||||
}
|
||||
#include <vector>
|
||||
|
||||
namespace openspace {
|
||||
ClipMapPyramid::ClipMapPyramid(Geodetic2 sizeLevel0)
|
||||
: _sizeLevel0(sizeLevel0)
|
||||
{
|
||||
|
||||
}
|
||||
class SkirtedGrid : 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.
|
||||
*/
|
||||
SkirtedGrid(
|
||||
unsigned int xSegments,
|
||||
unsigned int ySegments,
|
||||
TriangleSoup::Positions usePositions,
|
||||
TriangleSoup::TextureCoordinates useTextureCoordinates,
|
||||
TriangleSoup::Normals useNormals);
|
||||
~SkirtedGrid();
|
||||
|
||||
ClipMapPyramid::~ClipMapPyramid()
|
||||
{}
|
||||
|
||||
Geodetic2 ClipMapPyramid::getPatchSizeAtLevel(int level)
|
||||
{
|
||||
return Geodetic2(_sizeLevel0.lat / pow(2, level), _sizeLevel0.lon / pow(2, level));
|
||||
}
|
||||
virtual int xSegments() const;
|
||||
virtual int ySegments() const;
|
||||
|
||||
Geodetic2 ClipMapPyramid::getPatchSizeAtLevel0()
|
||||
{
|
||||
return _sizeLevel0;
|
||||
}
|
||||
private:
|
||||
virtual std::vector<GLuint> CreateElements(int xRes, int yRes);
|
||||
virtual std::vector<glm::vec4> CreatePositions(int xRes, int yRes);
|
||||
virtual std::vector<glm::vec2> CreateTextureCoordinates(int xRes, int yRes);
|
||||
virtual std::vector<glm::vec3> CreateNormals(int xRes, int yRes);
|
||||
|
||||
} // namespace openspace
|
||||
void validate(int xSegments, int ySegments);
|
||||
|
||||
inline size_t numElements(int xSegments, int ySegments);
|
||||
inline size_t numVertices(int xSegments, int ySegments);
|
||||
};
|
||||
} // namespace openspace
|
||||
#endif // __SKIRTEDGRID_H__
|
||||
@@ -44,29 +44,57 @@ namespace openspace {
|
||||
|
||||
void TileProviderManager::addHeightMap(
|
||||
std::string name,
|
||||
std::shared_ptr<TileProvider> tileProvider)
|
||||
std::shared_ptr<TileProvider> tileProvider,
|
||||
bool isActive)
|
||||
{
|
||||
_heightMapProviders.push_back(tileProvider);
|
||||
_heightMapProviders.push_back({ name , tileProvider, isActive});
|
||||
}
|
||||
|
||||
void TileProviderManager::addColorTexture(
|
||||
std::string name,
|
||||
std::shared_ptr<TileProvider> tileProvider)
|
||||
std::shared_ptr<TileProvider> tileProvider,
|
||||
bool isActive)
|
||||
{
|
||||
_colorTextureProviders.push_back(tileProvider);
|
||||
|
||||
_colorTextureProviders.push_back({ name , tileProvider, isActive });
|
||||
}
|
||||
|
||||
const std::vector<std::shared_ptr<TileProvider> >&
|
||||
std::vector<TileProviderManager::TileProviderWithName>&
|
||||
TileProviderManager::heightMapProviders()
|
||||
{
|
||||
return _heightMapProviders;
|
||||
}
|
||||
|
||||
const std::vector<std::shared_ptr<TileProvider> >&
|
||||
std::vector<TileProviderManager::TileProviderWithName>&
|
||||
TileProviderManager::colorTextureProviders()
|
||||
{
|
||||
return _colorTextureProviders;
|
||||
}
|
||||
|
||||
const std::vector<std::shared_ptr<TileProvider> >
|
||||
TileProviderManager::getActiveHeightMapProviders()
|
||||
{
|
||||
std::vector<std::shared_ptr<TileProvider> > tileProviders;
|
||||
for (auto it = _heightMapProviders.begin(); it != _heightMapProviders.end(); it++)
|
||||
{
|
||||
if (it->isActive) {
|
||||
tileProviders.push_back(it->tileProvider);
|
||||
}
|
||||
}
|
||||
return tileProviders;
|
||||
}
|
||||
|
||||
const std::vector<std::shared_ptr<TileProvider> >
|
||||
TileProviderManager::getActiveColorTextureProviders()
|
||||
{
|
||||
std::vector<std::shared_ptr<TileProvider> > tileProviders;
|
||||
for (auto it = _colorTextureProviders.begin(); it != _colorTextureProviders.end(); it++)
|
||||
{
|
||||
if (it->isActive) {
|
||||
tileProviders.push_back(it->tileProvider);
|
||||
}
|
||||
}
|
||||
return tileProviders;
|
||||
}
|
||||
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -37,23 +37,38 @@ namespace openspace {
|
||||
|
||||
class TileProviderManager {
|
||||
public:
|
||||
struct TileProviderWithName {
|
||||
std::string name;
|
||||
std::shared_ptr<TileProvider> tileProvider;
|
||||
bool isActive;
|
||||
};
|
||||
|
||||
TileProviderManager();
|
||||
~TileProviderManager();
|
||||
|
||||
static ThreadPool tileRequestThreadPool;
|
||||
|
||||
void addHeightMap(std::string name, std::shared_ptr<TileProvider> tileProvider);
|
||||
void addColorTexture(std::string name, std::shared_ptr<TileProvider> tileProvider);
|
||||
void addHeightMap(
|
||||
std::string name,
|
||||
std::shared_ptr<TileProvider> tileProvider,
|
||||
bool isActive);
|
||||
void addColorTexture(
|
||||
std::string name,
|
||||
std::shared_ptr<TileProvider> tileProvider,
|
||||
bool isActive);
|
||||
/*
|
||||
std::shared_ptr<TileProvider> getHeightMap(std::string name);
|
||||
std::shared_ptr<TileProvider> getColorTexture(std::string name);
|
||||
*/
|
||||
const std::vector<std::shared_ptr<TileProvider> >& heightMapProviders();
|
||||
const std::vector<std::shared_ptr<TileProvider> >& colorTextureProviders();
|
||||
const std::vector<std::shared_ptr<TileProvider> > getActiveHeightMapProviders();
|
||||
const std::vector<std::shared_ptr<TileProvider> > getActiveColorTextureProviders();
|
||||
|
||||
std::vector<TileProviderWithName>& heightMapProviders();
|
||||
std::vector<TileProviderWithName>& colorTextureProviders();
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<TileProvider> > _heightMapProviders;
|
||||
std::vector<std::shared_ptr<TileProvider> > _colorTextureProviders;
|
||||
std::vector<TileProviderWithName> _heightMapProviders;
|
||||
std::vector<TileProviderWithName> _colorTextureProviders;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
107
modules/globebrowsing/other/asynctilereader.cpp
Normal file
107
modules/globebrowsing/other/asynctilereader.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2016 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/filesystem/filesystem.h> // abspath
|
||||
#include <ghoul/misc/assert.h>
|
||||
|
||||
#include <modules/globebrowsing/other/asynctilereader.h>
|
||||
#include <modules/globebrowsing/other/tileprovider.h>
|
||||
#include <modules/globebrowsing/geodetics/angle.h>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "AsyncTextureDataProvider";
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace openspace {
|
||||
|
||||
|
||||
|
||||
AsyncTileDataProvider::AsyncTileDataProvider(
|
||||
std::shared_ptr<TileDataset> tileDataset,
|
||||
std::shared_ptr<ThreadPool> pool)
|
||||
: _tileDataset(tileDataset)
|
||||
, _concurrentJobManager(pool)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
AsyncTileDataProvider::~AsyncTileDataProvider() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<TileDataset> AsyncTileDataProvider::getTextureDataProvider() const {
|
||||
return _tileDataset;
|
||||
}
|
||||
|
||||
bool AsyncTileDataProvider::enqueueTextureData(const ChunkIndex& chunkIndex) {
|
||||
if (satisfiesEnqueueCriteria(chunkIndex)) {
|
||||
std::shared_ptr<TileLoadJob> job = std::shared_ptr<TileLoadJob>(
|
||||
new TileLoadJob(_tileDataset, chunkIndex));
|
||||
|
||||
_concurrentJobManager.enqueueJob(job);
|
||||
_enqueuedTileRequests[chunkIndex.hashKey()] = chunkIndex;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AsyncTileDataProvider::hasLoadedTextureData() const{
|
||||
return _concurrentJobManager.numFinishedJobs() > 0;
|
||||
}
|
||||
|
||||
std::shared_ptr<TileIOResult> AsyncTileDataProvider::nextTileIOResult() {
|
||||
auto tileIOResult = _concurrentJobManager.popFinishedJob()->product();
|
||||
HashKey key = tileIOResult->rawTileData->chunkIndex.hashKey();
|
||||
if (_enqueuedTileRequests.find(key) != _enqueuedTileRequests.end()) {
|
||||
_enqueuedTileRequests.erase(key);
|
||||
}
|
||||
return tileIOResult;
|
||||
}
|
||||
|
||||
|
||||
bool AsyncTileDataProvider::satisfiesEnqueueCriteria(const ChunkIndex& chunkIndex) const {
|
||||
auto it = _enqueuedTileRequests.begin();
|
||||
auto end = _enqueuedTileRequests.end();
|
||||
for (; it != end; it++) {
|
||||
const ChunkIndex& otherChunk = it->second;
|
||||
if (chunkIndex.level == otherChunk.level &&
|
||||
chunkIndex.manhattan(otherChunk) < 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void AsyncTileDataProvider::clearRequestQueue() {
|
||||
_concurrentJobManager.clearEnqueuedJobs();
|
||||
_enqueuedTileRequests.clear();
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
@@ -22,31 +22,99 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __CLIPMAPPYRAMID_H__
|
||||
#define __CLIPMAPPYRAMID_H__
|
||||
|
||||
// open space includes
|
||||
#ifndef __ASYNC_TILE_DATA_PROVIDER_H__
|
||||
#define __ASYNC_TILE_DATA_PROVIDER_H__
|
||||
|
||||
//#include <modules/globebrowsing/other/tileprovider.h>
|
||||
|
||||
#include <ghoul/opengl/texture.h>
|
||||
|
||||
#include <modules/globebrowsing/geodetics/geodetic2.h>
|
||||
|
||||
#include <modules/globebrowsing/other/concurrentjobmanager.h>
|
||||
#include <modules/globebrowsing/other/threadpool.h>
|
||||
#include <modules/globebrowsing/other/tiledataset.h>
|
||||
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
|
||||
namespace openspace {
|
||||
|
||||
|
||||
class ClipMapPyramid {
|
||||
public:
|
||||
/**
|
||||
\Param sizeLevel0 is the size of the biggest patch in the pyramid.
|
||||
The parameter needs to be M_PI / pow(2, i) where i is a positive or zero
|
||||
valued integer.
|
||||
*/
|
||||
ClipMapPyramid(Geodetic2 sizeLevel0);
|
||||
~ClipMapPyramid();
|
||||
|
||||
Geodetic2 getPatchSizeAtLevel(int level);
|
||||
Geodetic2 getPatchSizeAtLevel0();
|
||||
struct TileLoadJob : public Job<TileIOResult> {
|
||||
TileLoadJob(std::shared_ptr<TileDataset> textureDataProvider,
|
||||
const ChunkIndex& chunkIndex)
|
||||
: _tileDataset(textureDataProvider)
|
||||
, _chunkIndex(chunkIndex)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
virtual ~TileLoadJob() { }
|
||||
|
||||
virtual void execute() {
|
||||
_uninitedTexture = _tileDataset->readTileData(_chunkIndex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual std::shared_ptr<TileIOResult> product() {
|
||||
return _uninitedTexture;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
const Geodetic2 _sizeLevel0;
|
||||
ChunkIndex _chunkIndex;
|
||||
std::shared_ptr<TileDataset> _tileDataset;
|
||||
std::shared_ptr<TileIOResult> _uninitedTexture;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __CLIPMAPPYRAMID_H__
|
||||
|
||||
|
||||
|
||||
class AsyncTileDataProvider {
|
||||
public:
|
||||
|
||||
AsyncTileDataProvider(std::shared_ptr<TileDataset> textureDataProvider,
|
||||
std::shared_ptr<ThreadPool> pool);
|
||||
|
||||
~AsyncTileDataProvider();
|
||||
|
||||
|
||||
|
||||
bool enqueueTextureData(const ChunkIndex& chunkIndex);
|
||||
bool hasLoadedTextureData() const;
|
||||
std::shared_ptr<TileIOResult> nextTileIOResult();
|
||||
|
||||
void clearRequestQueue();
|
||||
|
||||
std::shared_ptr<TileDataset> getTextureDataProvider() const;
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool satisfiesEnqueueCriteria(const ChunkIndex&) const;
|
||||
|
||||
private:
|
||||
|
||||
std::shared_ptr<TileDataset> _tileDataset;
|
||||
ConcurrentJobManager<TileIOResult> _concurrentJobManager;
|
||||
std::unordered_map<HashKey, ChunkIndex> _enqueuedTileRequests;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // __ASYNC_TILE_DATA_PROVIDER_H__
|
||||
@@ -64,7 +64,7 @@ namespace openspace {
|
||||
template<typename P>
|
||||
class ConcurrentJobManager{
|
||||
public:
|
||||
ConcurrentJobManager(ThreadPool& pool) : threadPool(pool)
|
||||
ConcurrentJobManager(std::shared_ptr<ThreadPool> pool) : threadPool(pool)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -75,14 +75,14 @@ namespace openspace {
|
||||
|
||||
|
||||
void enqueueJob(std::shared_ptr<Job<P>> job) {
|
||||
threadPool.enqueue([this, job]() {
|
||||
threadPool->enqueue([this, job]() {
|
||||
job->execute();
|
||||
_finishedJobs.push(job);
|
||||
});
|
||||
}
|
||||
|
||||
void clearEnqueuedJobs() {
|
||||
threadPool.clearTasks();
|
||||
threadPool->clearTasks();
|
||||
}
|
||||
|
||||
std::shared_ptr<Job<P>> popFinishedJob() {
|
||||
@@ -90,7 +90,7 @@ namespace openspace {
|
||||
return _finishedJobs.pop();
|
||||
}
|
||||
|
||||
size_t numFinishedJobs() {
|
||||
size_t numFinishedJobs() const{
|
||||
return _finishedJobs.size();
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace openspace {
|
||||
private:
|
||||
|
||||
ConcurrentQueue<std::shared_ptr<Job<P>>> _finishedJobs;
|
||||
ThreadPool& threadPool;
|
||||
std::shared_ptr<ThreadPool> threadPool;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
_cond.notify_one();
|
||||
}
|
||||
|
||||
size_t size() {
|
||||
size_t size() const{
|
||||
std::unique_lock<std::mutex> mlock(_mutex);
|
||||
size_t s = _queue.size();
|
||||
mlock.unlock();
|
||||
@@ -87,8 +87,8 @@ public:
|
||||
|
||||
private:
|
||||
std::queue<T> _queue;
|
||||
std::mutex _mutex;
|
||||
std::condition_variable _cond;
|
||||
mutable std::mutex _mutex;
|
||||
mutable std::condition_variable _cond;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -107,6 +107,9 @@ namespace openspace {
|
||||
textureTypes[i].keyNumLayers, textureTypes[i].numLayers);
|
||||
}
|
||||
|
||||
// Remove old program
|
||||
_programObject.release();
|
||||
|
||||
_programObject = OsEng.renderEngine().buildRenderProgram(
|
||||
_shaderName,
|
||||
_vsPath,
|
||||
|
||||
@@ -1,182 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2016 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/globebrowsing/other/patchcoverageprovider.h>
|
||||
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "PatchCoverageProvider";
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
|
||||
PatchCoverageProvider::PatchCoverageProvider(
|
||||
Geodetic2 sizeLevel0,
|
||||
Geodetic2 offsetLevel0,
|
||||
int depth)
|
||||
: _sizeLevel0(sizeLevel0)
|
||||
, _offsetLevel0(offsetLevel0)
|
||||
, _depth(depth)
|
||||
{
|
||||
}
|
||||
|
||||
PatchCoverageProvider::~PatchCoverageProvider(){
|
||||
|
||||
}
|
||||
|
||||
ChunkIndex PatchCoverageProvider::getChunkIndex(const GeodeticPatch& patch) {
|
||||
// Calculate the level of the index depending on the size of the incoming patch.
|
||||
// The level is as big as possible (as far down as possible) but it can't be
|
||||
// too big since at maximum four tiles should be used to cover a patch
|
||||
int level = log2(static_cast<int>(glm::max(
|
||||
_sizeLevel0.lat / (patch.size().lat),
|
||||
_sizeLevel0.lon / (patch.size().lon))));
|
||||
|
||||
// If the depth is not big enough, the level must be clamped.
|
||||
level = glm::min(level, _depth);
|
||||
|
||||
// Calculate the index in x y where the tile should be positioned
|
||||
int nIndices = pow(2, level);
|
||||
Geodetic2 tileSize = _sizeLevel0 / nIndices;
|
||||
Geodetic2 nw = patch.northWestCorner();
|
||||
glm::ivec2 chunkIndexXY =
|
||||
glm::floor((nw.toLonLatVec2() - _offsetLevel0.toLonLatVec2()) / tileSize.toLonLatVec2());
|
||||
|
||||
// Flip y since indices increase from top to bottom
|
||||
chunkIndexXY.y = nIndices - 1 - chunkIndexXY.y;
|
||||
|
||||
// Create the tileindex
|
||||
ChunkIndex chunkIndex = { chunkIndexXY.x, chunkIndexXY.y, level };
|
||||
return chunkIndex;
|
||||
}
|
||||
|
||||
glm::mat3 PatchCoverageProvider::getUvTransformationPatchToTile(
|
||||
GeodeticPatch patch,
|
||||
const ChunkIndex& chunkIndex)
|
||||
{
|
||||
GeodeticPatch otherPatch(chunkIndex);
|
||||
return getUvTransformationPatchToTile(patch, otherPatch);
|
||||
}
|
||||
|
||||
|
||||
|
||||
glm::mat3 PatchCoverageProvider::getUvTransformationPatchToTile(
|
||||
GeodeticPatch patch,
|
||||
GeodeticPatch tile)
|
||||
{
|
||||
Vec2 posDiff =
|
||||
patch.southWestCorner().toLonLatVec2() -
|
||||
tile.southWestCorner().toLonLatVec2();
|
||||
|
||||
glm::mat3 invTileScale = glm::mat3(
|
||||
{ 1 / (tile.size().lon), 0, 0,
|
||||
0, 1 / (tile.size().lat), 0,
|
||||
0, 0, 1 });
|
||||
|
||||
glm::mat3 globalTranslation = glm::mat3(
|
||||
{ 1, 0, 0,
|
||||
0, 1, 0,
|
||||
posDiff.x, posDiff.y, 1 });
|
||||
|
||||
glm::mat3 patchScale = glm::mat3(
|
||||
{ (patch.halfSize().lon * 2), 0, 0,
|
||||
0, (patch.halfSize().lat * 2), 0,
|
||||
0, 0, 1 });
|
||||
|
||||
return invTileScale * globalTranslation * patchScale;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PatchCoverage PatchCoverageProvider::getCoverage(
|
||||
GeodeticPatch patch,
|
||||
std::shared_ptr<TileProvider> tileProvider)
|
||||
{
|
||||
static const int numTilesInCoverageX = 2;
|
||||
static const int numTilesInCoverageY = 2;
|
||||
PatchCoverage patchCoverageToReturn;
|
||||
|
||||
Geodetic2 startPoint = patch.northWestCorner();
|
||||
int level = (int) patch.minimumTileLevel();
|
||||
ChunkIndex startIndex = ChunkIndex(startPoint, level);
|
||||
|
||||
for (int y = 0; y < numTilesInCoverageY; y++)
|
||||
{
|
||||
for (int x = 0; x < numTilesInCoverageX; x++)
|
||||
{
|
||||
int linearIdx = x + y * numTilesInCoverageX;
|
||||
|
||||
// May return negative indices
|
||||
ChunkIndex chunkIndex = getChunkIndex(patch);
|
||||
// Offset chunkIndex
|
||||
chunkIndex.x += x;
|
||||
chunkIndex.y += y;
|
||||
|
||||
|
||||
// If the tile index is negative or too big it needs to wrap around
|
||||
int nIndices = pow(2, chunkIndex.level);
|
||||
ChunkIndex positiveChunkIndex = ChunkIndex(chunkIndex);
|
||||
positiveChunkIndex.x += (chunkIndex.x < 0) ? nIndices : ((chunkIndex.x > nIndices - 1) ? -nIndices : 0);
|
||||
positiveChunkIndex.y += (chunkIndex.y < 0) ? nIndices : ((chunkIndex.y > nIndices - 1) ? -nIndices : 0);
|
||||
|
||||
|
||||
|
||||
int numLevelsToLoop = chunkIndex.level;
|
||||
// Start at the highest level and go down if the texture don't exist
|
||||
for (int j = numLevelsToLoop; j >= 0; j--)
|
||||
{
|
||||
// Try if the texture exists
|
||||
std::shared_ptr<Texture> tile = tileProvider->getOrStartFetchingTile(positiveChunkIndex);
|
||||
if (tile == nullptr)
|
||||
{ // If it doesn't exist, go down a level
|
||||
chunkIndex.x /= 2;
|
||||
chunkIndex.y /= 2;
|
||||
chunkIndex.level -= 1;
|
||||
}
|
||||
else
|
||||
{ // A texture was found, put it in the data structure to return
|
||||
patchCoverageToReturn.textureTransformPairs[linearIdx].first =
|
||||
tile;
|
||||
patchCoverageToReturn.textureTransformPairs[linearIdx].second =
|
||||
getUvTransformationPatchToTile(patch, chunkIndex);
|
||||
}
|
||||
}
|
||||
// If the texture still doesn't exist put a temporary texture
|
||||
if (patchCoverageToReturn.textureTransformPairs[linearIdx].first == nullptr)
|
||||
{
|
||||
patchCoverageToReturn.textureTransformPairs[linearIdx].first =
|
||||
tileProvider->getDefaultTexture();
|
||||
patchCoverageToReturn.textureTransformPairs[linearIdx].second =
|
||||
getUvTransformationPatchToTile(patch, chunkIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return patchCoverageToReturn;
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
119
modules/globebrowsing/other/temporaltileprovider.cpp
Normal file
119
modules/globebrowsing/other/temporaltileprovider.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2016 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/globebrowsing/geodetics/geodetic2.h>
|
||||
#include <modules/globebrowsing/other/temporaltileprovider.h>
|
||||
|
||||
#include <modules/globebrowsing/globes/chunkindex.h>
|
||||
|
||||
#include <openspace/engine/downloadmanager.h>
|
||||
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
|
||||
#include <openspace/util/time.h>
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <streambuf>
|
||||
|
||||
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "TemporalTileProvider";
|
||||
}
|
||||
|
||||
|
||||
namespace openspace {
|
||||
|
||||
const std::string TemporalTileProvider::TIME_PLACEHOLDER("${t}");
|
||||
|
||||
TemporalTileProvider::TemporalTileProvider(const std::string& datasetFile,
|
||||
const TileProviderInitData& tileProviderInitData)
|
||||
: _datasetFile(datasetFile)
|
||||
, _tileProviderInitData(tileProviderInitData)
|
||||
{
|
||||
std::ifstream in(datasetFile.c_str());
|
||||
ghoul_assert(errno == 0, strerror(errno) << std::endl << datasetFile);
|
||||
|
||||
// read file
|
||||
std::string str( (std::istreambuf_iterator<char>(in)), (std::istreambuf_iterator<char>()));
|
||||
_dataSourceXmlTemplate = std::string(str);
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<TileProvider> TemporalTileProvider::getTileProvider(Time t) {
|
||||
TimeKey timekey = getTimeKey(t);
|
||||
auto it = _tileProviderMap.find(timekey);
|
||||
if (it != _tileProviderMap.end()) {
|
||||
return it->second;
|
||||
}
|
||||
else {
|
||||
auto tileProvider = initTileProvider(timekey);
|
||||
_tileProviderMap[timekey] = tileProvider;
|
||||
return tileProvider;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<TileProvider> TemporalTileProvider::initTileProvider(TimeKey timekey) {
|
||||
std::string gdalDatasetXml = getGdalDatasetXML(timekey);
|
||||
|
||||
std::shared_ptr<TileDataset> tileDataset = std::shared_ptr<TileDataset>(
|
||||
new TileDataset(gdalDatasetXml, _tileProviderInitData.minimumPixelSize));
|
||||
|
||||
std::shared_ptr<ThreadPool> threadPool = std::shared_ptr<ThreadPool>(
|
||||
new ThreadPool(_tileProviderInitData.threads));
|
||||
|
||||
std::shared_ptr<AsyncTileDataProvider> tileReader = std::shared_ptr<AsyncTileDataProvider>(
|
||||
new AsyncTileDataProvider(tileDataset, threadPool));
|
||||
|
||||
std::shared_ptr<TileProvider> tileProvider= std::shared_ptr<TileProvider>(
|
||||
new TileProvider(tileReader,
|
||||
_tileProviderInitData.cacheSize,
|
||||
_tileProviderInitData.framesUntilRequestQueueFlush));
|
||||
|
||||
return tileProvider;
|
||||
}
|
||||
|
||||
TemporalTileProvider::TimeKey TemporalTileProvider::getTimeKey(const Time& t) {
|
||||
std::string datestring = t.ISO8601();
|
||||
datestring = datestring.substr(0, 10);
|
||||
return datestring;
|
||||
}
|
||||
|
||||
std::string TemporalTileProvider::getGdalDatasetXML(Time t) {
|
||||
return getGdalDatasetXML(getTimeKey(t));
|
||||
}
|
||||
|
||||
std::string TemporalTileProvider::getGdalDatasetXML(TimeKey timeKey) {
|
||||
std::string xmlTemplate(_dataSourceXmlTemplate);
|
||||
size_t pos = xmlTemplate.find(TIME_PLACEHOLDER);
|
||||
size_t numChars = TIME_PLACEHOLDER.length();
|
||||
ghoul_assert(pos != std::string::npos, "Invalid dataset file");
|
||||
std::string timeSpecifiedXml = xmlTemplate.replace(pos, numChars, timeKey);
|
||||
return timeSpecifiedXml;
|
||||
}
|
||||
|
||||
|
||||
} // namespace openspace
|
||||
@@ -22,73 +22,77 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __PATCHCOVERAGEPROVIDER_H__
|
||||
#define __PATCHCOVERAGEPROVIDER_H__
|
||||
#ifndef __TEMPORAL_TILE_PROVIDER_H__
|
||||
#define __TEMPORAL_TILE_PROVIDER_H__
|
||||
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
|
||||
#include <modules/globebrowsing/globes/chunkindex.h>
|
||||
#include <ghoul/opengl/texture.h>
|
||||
|
||||
#include <modules/globebrowsing/geodetics/geodetic2.h>
|
||||
#include <modules/globebrowsing/other/tileprovider.h>
|
||||
#include <ghoul/opengl/texture.h>
|
||||
#include <openspace/util/time.h>
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "gdal_priv.h"
|
||||
#include "vrtdataset.h"
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PATCH COVERAGE PROVIDER //
|
||||
// TILE PROVIDER //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace openspace {
|
||||
|
||||
using namespace ghoul::opengl;
|
||||
|
||||
struct PatchCoverage
|
||||
{
|
||||
using TextureTransformPair = std::pair<std::shared_ptr<Texture>, glm::mat3>;
|
||||
TextureTransformPair textureTransformPairs[4];
|
||||
|
||||
struct TileProviderInitData {
|
||||
int minimumPixelSize;
|
||||
int threads;
|
||||
int cacheSize;
|
||||
int framesUntilRequestQueueFlush;
|
||||
};
|
||||
|
||||
class PatchCoverageProvider
|
||||
{
|
||||
|
||||
class TemporalTileProvider {
|
||||
public:
|
||||
PatchCoverageProvider(
|
||||
Geodetic2 sizeLevel0,
|
||||
Geodetic2 offsetLevel0,
|
||||
int depth);
|
||||
~PatchCoverageProvider();
|
||||
TemporalTileProvider(const std::string& datasetFile, const TileProviderInitData& tileProviderInitData);
|
||||
|
||||
/**
|
||||
Returns the index of the tile at an appropriate level.
|
||||
Appropriate meaning that the tile should be at as high level as possible
|
||||
Without the tile being smaller than the patch in lat-lon space.
|
||||
The tile is at least as big as the patch.
|
||||
*/
|
||||
ChunkIndex getChunkIndex(const GeodeticPatch& patch);
|
||||
|
||||
/**
|
||||
A transformation (translation and scaling) from the texture space of a patch
|
||||
to the texture space of a tile.
|
||||
*/
|
||||
glm::mat3 getUvTransformationPatchToTile(
|
||||
GeodeticPatch patch,
|
||||
const ChunkIndex& chunkIndex);
|
||||
|
||||
/**
|
||||
Overloaded function
|
||||
*/
|
||||
glm::mat3 getUvTransformationPatchToTile(
|
||||
GeodeticPatch patch,
|
||||
GeodeticPatch tile);
|
||||
|
||||
PatchCoverage getCoverage(
|
||||
GeodeticPatch patch,
|
||||
std::shared_ptr<TileProvider> tileProvider);
|
||||
std::shared_ptr<TileProvider> getTileProvider(Time t = Time::ref());
|
||||
|
||||
private:
|
||||
Geodetic2 _sizeLevel0;
|
||||
Geodetic2 _offsetLevel0;
|
||||
int _depth;
|
||||
|
||||
typedef std::string TimeKey;
|
||||
|
||||
std::string getGdalDatasetXML(Time t);
|
||||
std::string getGdalDatasetXML(TimeKey key);
|
||||
|
||||
static const std::string TIME_PLACEHOLDER;
|
||||
|
||||
TimeKey getTimeKey(const Time& t);
|
||||
|
||||
std::shared_ptr<TileProvider> initTileProvider(TimeKey timekey);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Members variables //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const std::string _datasetFile;
|
||||
|
||||
std::string _dataSourceXmlTemplate;
|
||||
|
||||
std::unordered_map<TimeKey, std::shared_ptr<TileProvider> > _tileProviderMap;
|
||||
|
||||
TileProviderInitData _tileProviderInitData;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __PATCHCOVERAGEPROVIDER_H__
|
||||
|
||||
|
||||
|
||||
#endif // __TEMPORAL_TILE_PROVIDER_H__
|
||||
@@ -27,12 +27,14 @@
|
||||
#include <ghoul/filesystem/filesystem.h> // abspath
|
||||
#include <ghoul/misc/assert.h>
|
||||
|
||||
#include <modules/globebrowsing/other/texturedataprovider.h>
|
||||
#include <modules/globebrowsing/other/tiledataset.h>
|
||||
#include <modules/globebrowsing/other/tileprovider.h>
|
||||
#include <modules/globebrowsing/geodetics/angle.h>
|
||||
|
||||
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "TextureDataProvider";
|
||||
const std::string _loggerCat = "TileDataset";
|
||||
}
|
||||
|
||||
|
||||
@@ -40,42 +42,42 @@ namespace {
|
||||
namespace openspace {
|
||||
|
||||
// INIT THIS TO FALSE AFTER REMOVED FROM TILEPROVIDER
|
||||
bool TextureDataProvider::GdalHasBeenInitialized = false;
|
||||
bool TileDataset::GdalHasBeenInitialized = false;
|
||||
|
||||
TextureDataProvider::TextureDataProvider(const std::string& fileName, int minimumPixelSize)
|
||||
TileDataset::TileDataset(const std::string& gdalDatasetDesc, int minimumPixelSize, GLuint dataType)
|
||||
: _minimumPixelSize(minimumPixelSize)
|
||||
{
|
||||
|
||||
if (!GdalHasBeenInitialized) {
|
||||
GDALAllRegister();
|
||||
GdalHasBeenInitialized = true;
|
||||
}
|
||||
|
||||
_dataset = (GDALDataset *)GDALOpen(absPath(fileName).c_str(), GA_ReadOnly);
|
||||
ghoul_assert(_dataset != nullptr, "Failed to load dataset: " << fileName);
|
||||
_dataset = (GDALDataset *)GDALOpen(gdalDatasetDesc.c_str(), GA_ReadOnly);
|
||||
ghoul_assert(_dataset != nullptr, "Failed to load dataset:\n" << gdalDatasetDesc);
|
||||
_dataLayout = DataLayout(_dataset, dataType);
|
||||
|
||||
_depthTransform = calculateTileDepthTransform();
|
||||
_tileLevelDifference = calculateTileLevelDifference(_dataset, minimumPixelSize);
|
||||
}
|
||||
|
||||
|
||||
TextureDataProvider::~TextureDataProvider() {
|
||||
TileDataset::~TileDataset() {
|
||||
delete _dataset;
|
||||
}
|
||||
|
||||
int TextureDataProvider::calculateTileLevelDifference(GDALDataset* dataset, int minimumPixelSize) {
|
||||
int TileDataset::calculateTileLevelDifference(GDALDataset* dataset, int minimumPixelSize) {
|
||||
GDALRasterBand* firstBand = dataset->GetRasterBand(1);
|
||||
int numOverviews = firstBand->GetOverviewCount();
|
||||
int sizeLevel0 = firstBand->GetOverview(numOverviews - 1)->GetXSize();
|
||||
return log2(minimumPixelSize) - log2(sizeLevel0);
|
||||
}
|
||||
|
||||
TileDepthTransform TextureDataProvider::calculateTileDepthTransform() {
|
||||
TileDepthTransform TileDataset::calculateTileDepthTransform() {
|
||||
GDALRasterBand* firstBand = _dataset->GetRasterBand(1);
|
||||
GDALDataType gdalType = firstBand->GetRasterDataType();
|
||||
|
||||
double maximumValue = (gdalType == GDT_Float32 || gdalType == GDT_Float64) ?
|
||||
1.0 : firstBand->GetMaximum();
|
||||
// Floating point types does not have a fix maximum or minimum value and
|
||||
// can not be normalized when sampling a texture. Hence no rescaling is needed.
|
||||
double maximumValue = (_dataLayout.gdalType == GDT_Float32 || _dataLayout.gdalType == GDT_Float64) ?
|
||||
1.0 : getMaximumValue(_dataLayout.gdalType);
|
||||
|
||||
TileDepthTransform transform;
|
||||
transform.depthOffset = firstBand->GetOffset();
|
||||
@@ -83,21 +85,22 @@ namespace openspace {
|
||||
return transform;
|
||||
}
|
||||
|
||||
int TextureDataProvider::getMaximumLevel() const {
|
||||
int TileDataset::getMaximumLevel() const {
|
||||
int numOverviews = _dataset->GetRasterBand(1)->GetOverviewCount();
|
||||
int maximumLevel = numOverviews - 1 - _tileLevelDifference;
|
||||
return maximumLevel;
|
||||
}
|
||||
|
||||
TileDepthTransform TextureDataProvider::getDepthTransform() const {
|
||||
TileDepthTransform TileDataset::getDepthTransform() const {
|
||||
return _depthTransform;
|
||||
}
|
||||
|
||||
std::shared_ptr<TileIOResult> TextureDataProvider::getTextureData(ChunkIndex chunkIndex)
|
||||
std::shared_ptr<TileIOResult> TileDataset::readTileData(ChunkIndex chunkIndex)
|
||||
{
|
||||
GdalDataRegion region(_dataset, chunkIndex, _tileLevelDifference);
|
||||
DataLayout dataLayout(_dataset, region);
|
||||
char* imageData = new char[dataLayout.totalNumBytes];
|
||||
size_t bytesPerLine = _dataLayout.bytesPerPixel * region.numPixels.x;
|
||||
size_t totalNumBytes = bytesPerLine * region.numPixels.y;
|
||||
char* imageData = new char[totalNumBytes];
|
||||
|
||||
CPLErr worstError = CPLErr::CE_None;
|
||||
|
||||
@@ -105,7 +108,7 @@ namespace openspace {
|
||||
for (size_t i = 0; i < region.numRasters; i++) {
|
||||
GDALRasterBand* rasterBand = _dataset->GetRasterBand(i + 1)->GetOverview(region.overview);
|
||||
|
||||
char* dataDestination = imageData + (i * dataLayout.bytesPerDatum);
|
||||
char* dataDestination = imageData + (i * _dataLayout.bytesPerDatum);
|
||||
|
||||
CPLErr err = rasterBand->RasterIO(
|
||||
GF_Read,
|
||||
@@ -116,16 +119,16 @@ namespace openspace {
|
||||
dataDestination, // Where to put data
|
||||
region.numPixels.x, // width to write x in destination
|
||||
region.numPixels.y, // width to write y in destination
|
||||
dataLayout.gdalType, // Type
|
||||
dataLayout.bytesPerPixel, // Pixel spacing
|
||||
dataLayout.bytesPerLine); // Line spacing
|
||||
_dataLayout.gdalType, // Type
|
||||
_dataLayout.bytesPerPixel, // Pixel spacing
|
||||
bytesPerLine); // Line spacing
|
||||
|
||||
// CE_None = 0, CE_Debug = 1, CE_Warning = 2, CE_Failure = 3, CE_Fatal = 4
|
||||
worstError = std::max(worstError, err);
|
||||
}
|
||||
|
||||
std::shared_ptr<RawTileData> tileData = nullptr;
|
||||
tileData = createRawTileData(region, dataLayout, imageData);
|
||||
tileData = createRawTileData(region, _dataLayout, imageData);
|
||||
|
||||
std::shared_ptr<TileIOResult> result(new TileIOResult);
|
||||
result->error = worstError;
|
||||
@@ -135,18 +138,20 @@ namespace openspace {
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<RawTileData> TextureDataProvider::createRawTileData(const GdalDataRegion& region,
|
||||
std::shared_ptr<RawTileData> TileDataset::createRawTileData(const GdalDataRegion& region,
|
||||
const DataLayout& dataLayout, const char* imageData)
|
||||
{
|
||||
|
||||
size_t bytesPerLine = dataLayout.bytesPerPixel * region.numPixels.x;
|
||||
size_t totalNumBytes = bytesPerLine * region.numPixels.y;
|
||||
|
||||
//if(cplError == CPLErr::CE_Fatal)
|
||||
|
||||
// GDAL reads image data top to bottom. We want the opposite.
|
||||
char* imageDataYflipped = new char[dataLayout.totalNumBytes];
|
||||
char* imageDataYflipped = new char[totalNumBytes];
|
||||
for (size_t y = 0; y < region.numPixels.y; y++) {
|
||||
for (size_t x = 0; x < dataLayout.bytesPerLine; x++) {
|
||||
imageDataYflipped[x + y * dataLayout.bytesPerLine] =
|
||||
imageData[x + (region.numPixels.y - 1 - y) * dataLayout.bytesPerLine];
|
||||
for (size_t x = 0; x < bytesPerLine; x++) {
|
||||
imageDataYflipped[x + y * bytesPerLine] =
|
||||
imageData[x + (region.numPixels.y - 1 - y) * bytesPerLine];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,7 +173,7 @@ namespace openspace {
|
||||
|
||||
|
||||
|
||||
size_t TextureDataProvider::numberOfBytes(GDALDataType gdalType) {
|
||||
size_t TileDataset::numberOfBytes(GDALDataType gdalType) {
|
||||
switch (gdalType) {
|
||||
case GDT_Byte: return sizeof(GLubyte);
|
||||
case GDT_UInt16: return sizeof(GLushort);
|
||||
@@ -178,13 +183,27 @@ namespace openspace {
|
||||
case GDT_Float32: return sizeof(GLfloat);
|
||||
case GDT_Float64: return sizeof(GLdouble);
|
||||
default:
|
||||
//LERROR("Unknown data type");
|
||||
LERROR("Unknown data type");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
size_t TileDataset::getMaximumValue(GDALDataType gdalType) {
|
||||
switch (gdalType) {
|
||||
case GDT_Byte: return 2 << 7;
|
||||
case GDT_UInt16: return 2 << 15;
|
||||
case GDT_Int16: return 2 << 14;
|
||||
case GDT_UInt32: return 2 << 31;
|
||||
case GDT_Int32: return 2 << 30;
|
||||
default:
|
||||
LERROR("Unknown data type");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
glm::uvec2 TextureDataProvider::geodeticToPixel(GDALDataset* dataSet, const Geodetic2& geo) {
|
||||
glm::uvec2 TileDataset::geodeticToPixel(GDALDataset* dataSet, const Geodetic2& geo) {
|
||||
double padfTransform[6];
|
||||
CPLErr err = dataSet->GetGeoTransform(padfTransform);
|
||||
|
||||
@@ -222,7 +241,7 @@ namespace openspace {
|
||||
}
|
||||
|
||||
|
||||
RawTileData::TextureFormat TextureDataProvider::getTextureFormat(
|
||||
RawTileData::TextureFormat TileDataset::getTextureFormat(
|
||||
int rasterCount, GDALDataType gdalType)
|
||||
{
|
||||
RawTileData::TextureFormat format;
|
||||
@@ -238,7 +257,7 @@ namespace openspace {
|
||||
case GDT_Int32: format.glFormat = GL_R32I; break;
|
||||
case GDT_Float32: format.glFormat = GL_R32F; break;
|
||||
//case GDT_Float64: format.glFormat = GL_RED; break; // No representation of 64 bit float?
|
||||
default: ;//LERROR("GDAL data type unknown to OpenGL: " << gdalType);
|
||||
default: LERROR("GDAL data type unknown to OpenGL: " << gdalType);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
@@ -251,7 +270,7 @@ namespace openspace {
|
||||
case GDT_Int32: format.glFormat = GL_RG32I; break;
|
||||
case GDT_Float32: format.glFormat = GL_RG32F; break;
|
||||
case GDT_Float64: format.glFormat = GL_RED; break; // No representation of 64 bit float?
|
||||
default: ;//LERROR("GDAL data type unknown to OpenGL: " << gdalType);
|
||||
default: LERROR("GDAL data type unknown to OpenGL: " << gdalType);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
@@ -264,7 +283,7 @@ namespace openspace {
|
||||
case GDT_Int32: format.glFormat = GL_RGB32I; break;
|
||||
case GDT_Float32: format.glFormat = GL_RGB32F; break;
|
||||
// case GDT_Float64: format.glFormat = GL_RED; break;// No representation of 64 bit float?
|
||||
default: ;//LERROR("GDAL data type unknown to OpenGL: " << gdalType);
|
||||
default: LERROR("GDAL data type unknown to OpenGL: " << gdalType);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
@@ -277,11 +296,11 @@ namespace openspace {
|
||||
case GDT_Int32: format.glFormat = GL_RGBA32I; break;
|
||||
case GDT_Float32: format.glFormat = GL_RGBA32F; break;
|
||||
case GDT_Float64: format.glFormat = GL_RED; break; // No representation of 64 bit float?
|
||||
default: ;//LERROR("GDAL data type unknown to OpenGL: " << gdalType);
|
||||
default: LERROR("GDAL data type unknown to OpenGL: " << gdalType);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//LERROR("Unknown number of channels for OpenGL texture: " << rasterCount);
|
||||
LERROR("Unknown number of channels for OpenGL texture: " << rasterCount);
|
||||
break;
|
||||
}
|
||||
return format;
|
||||
@@ -292,7 +311,7 @@ namespace openspace {
|
||||
|
||||
|
||||
|
||||
GLuint TextureDataProvider::getOpenGLDataType(GDALDataType gdalType) {
|
||||
GLuint TileDataset::getOpenGLDataType(GDALDataType gdalType) {
|
||||
switch (gdalType) {
|
||||
case GDT_Byte: return GL_UNSIGNED_BYTE;
|
||||
case GDT_UInt16: return GL_UNSIGNED_SHORT;
|
||||
@@ -302,13 +321,28 @@ namespace openspace {
|
||||
case GDT_Float32: return GL_FLOAT;
|
||||
case GDT_Float64: return GL_DOUBLE;
|
||||
default:
|
||||
//LERROR("GDAL data type unknown to OpenGL: " << gdalType);
|
||||
LERROR("GDAL data type unknown to OpenGL: " << gdalType);
|
||||
return GL_UNSIGNED_BYTE;
|
||||
}
|
||||
}
|
||||
|
||||
GDALDataType TileDataset::getGdalDataType(GLuint glType) {
|
||||
switch (glType) {
|
||||
case GL_UNSIGNED_BYTE: return GDT_Byte;
|
||||
case GL_UNSIGNED_SHORT: return GDT_UInt16;
|
||||
case GL_SHORT: return GDT_Int16;
|
||||
case GL_UNSIGNED_INT: return GDT_UInt32;
|
||||
case GL_INT: return GDT_Int32;
|
||||
case GL_FLOAT: return GDT_Float32;
|
||||
case GL_DOUBLE: return GDT_Float64;
|
||||
default:
|
||||
LERROR("OpenGL data type unknown to GDAL: " << glType);
|
||||
return GDT_Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
TextureDataProvider::GdalDataRegion::GdalDataRegion(GDALDataset * dataSet,
|
||||
|
||||
TileDataset::GdalDataRegion::GdalDataRegion(GDALDataset * dataSet,
|
||||
const ChunkIndex& chunkIndex, int tileLevelDifference)
|
||||
: chunkIndex(chunkIndex)
|
||||
{
|
||||
@@ -351,14 +385,14 @@ namespace openspace {
|
||||
numPixels = pixelEnd - pixelStart;
|
||||
}
|
||||
|
||||
TileDataset::DataLayout::DataLayout() {
|
||||
}
|
||||
|
||||
TextureDataProvider::DataLayout::DataLayout(GDALDataset* dataSet, const GdalDataRegion& region) {
|
||||
TileDataset::DataLayout::DataLayout(GDALDataset* dataSet, GLuint glType) {
|
||||
// Assume all raster bands have the same data type
|
||||
gdalType = dataSet->GetRasterBand(1)->GetRasterDataType();
|
||||
gdalType = glType != 0 ? getGdalDataType(glType) : dataSet->GetRasterBand(1)->GetRasterDataType();
|
||||
bytesPerDatum = numberOfBytes(gdalType);
|
||||
bytesPerPixel = bytesPerDatum * region.numRasters;
|
||||
bytesPerLine = bytesPerPixel * region.numPixels.x;
|
||||
totalNumBytes = bytesPerLine * region.numPixels.y;
|
||||
bytesPerPixel = bytesPerDatum * dataSet->GetRasterCount();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __TEXTURE_DATA_PROVIDER_H__
|
||||
#define __TEXTURE_DATA_PROVIDER_H__
|
||||
#ifndef __TILE_DATASET_H__
|
||||
#define __TILE_DATASET_H__
|
||||
|
||||
//#include <modules/globebrowsing/other/tileprovider.h>
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
#include "gdal_priv.h"
|
||||
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <queue>
|
||||
@@ -86,14 +87,26 @@ namespace openspace {
|
||||
|
||||
|
||||
|
||||
class TextureDataProvider {
|
||||
class TileDataset {
|
||||
public:
|
||||
|
||||
TextureDataProvider(const std::string& fileName, int minimumPixelSize);
|
||||
~TextureDataProvider();
|
||||
|
||||
/**
|
||||
* Opens a GDALDataset in readonly mode and calculates meta data required for
|
||||
* reading tile using a ChunkIndex.
|
||||
*
|
||||
* \param gdalDatasetDesc - A path to a specific file or raw XML describing the dataset
|
||||
* \param minimumPixelSize - minimum number of pixels per side per tile requested
|
||||
* \param datatype - datatype for storing pixel data in requested tile
|
||||
*/
|
||||
TileDataset(const std::string& gdalDatasetDesc, int minimumPixelSize, GLuint dataType = 0);
|
||||
|
||||
~TileDataset();
|
||||
|
||||
|
||||
|
||||
|
||||
std::shared_ptr<TileIOResult> getTextureData(ChunkIndex chunkIndex);
|
||||
std::shared_ptr<TileIOResult> readTileData(ChunkIndex chunkIndex);
|
||||
|
||||
int getMaximumLevel() const;
|
||||
|
||||
@@ -103,6 +116,7 @@ namespace openspace {
|
||||
private:
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// HELPER STRUCTS //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -126,13 +140,12 @@ namespace openspace {
|
||||
};
|
||||
|
||||
struct DataLayout {
|
||||
DataLayout(GDALDataset* dataSet, const GdalDataRegion& region);
|
||||
DataLayout();
|
||||
DataLayout(GDALDataset* dataSet, GLuint glType);
|
||||
|
||||
GDALDataType gdalType;
|
||||
size_t bytesPerDatum;
|
||||
size_t bytesPerPixel;
|
||||
size_t bytesPerLine;
|
||||
size_t totalNumBytes;
|
||||
};
|
||||
|
||||
|
||||
@@ -153,10 +166,14 @@ namespace openspace {
|
||||
|
||||
static GLuint getOpenGLDataType(GDALDataType gdalType);
|
||||
|
||||
static GDALDataType getGdalDataType(GLuint glType);
|
||||
|
||||
static RawTileData::TextureFormat getTextureFormat(int rasterCount, GDALDataType gdalType);
|
||||
|
||||
static size_t numberOfBytes(GDALDataType gdalType);
|
||||
|
||||
static size_t getMaximumValue(GDALDataType gdalType);
|
||||
|
||||
static std::shared_ptr<RawTileData> createRawTileData(const GdalDataRegion& region,
|
||||
const DataLayout& dataLayout, const char* imageData);
|
||||
|
||||
@@ -173,6 +190,7 @@ namespace openspace {
|
||||
TileDepthTransform _depthTransform;
|
||||
|
||||
GDALDataset* _dataset;
|
||||
DataLayout _dataLayout;
|
||||
|
||||
};
|
||||
|
||||
@@ -184,4 +202,4 @@ namespace openspace {
|
||||
|
||||
|
||||
|
||||
#endif // __TEXTURE_DATA_PROVIDER_H__
|
||||
#endif // __TILE_DATASET_H__
|
||||
@@ -46,79 +46,48 @@ namespace {
|
||||
|
||||
namespace openspace {
|
||||
|
||||
|
||||
|
||||
|
||||
TileProvider::TileProvider(
|
||||
const std::string& filePath,
|
||||
int tileCacheSize,
|
||||
int minimumPixelSize,
|
||||
int framesUntilRequestFlush)
|
||||
: _filePath(filePath)
|
||||
, _tileCache(tileCacheSize) // setting cache size
|
||||
TileProvider::TileProvider(std::shared_ptr<AsyncTileDataProvider> tileReader, int tileCacheSize,
|
||||
int framesUntilFlushRequestQueue)
|
||||
: _asyncTextureDataProvider(tileReader)
|
||||
, _tileCache(tileCacheSize)
|
||||
, _framesSinceLastRequestFlush(0)
|
||||
, _framesUntilRequestFlush(framesUntilRequestFlush)
|
||||
, _tileLoadManager(TileProviderManager::tileRequestThreadPool)
|
||||
, _rawTextureTileDataProvider(filePath, minimumPixelSize)
|
||||
{
|
||||
// Set a temporary texture
|
||||
std::string fileName = "textures/earth_bluemarble.jpg";
|
||||
_defaultTexture = std::move(ghoul::io::TextureReader::ref().loadTexture(absPath(fileName)));
|
||||
|
||||
if (_defaultTexture) {
|
||||
LDEBUG("Loaded texture from '" << fileName << "'");
|
||||
_defaultTexture->uploadTexture();
|
||||
|
||||
// Textures of planets looks much smoother with AnisotropicMipMap rather than linear
|
||||
// TODO: AnisotropicMipMap crashes on ATI cards ---abock
|
||||
//_testTexture->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap);
|
||||
_defaultTexture->setFilter(ghoul::opengl::Texture::FilterMode::Linear);
|
||||
_defaultTexture->setWrapping(ghoul::opengl::Texture::WrappingMode::ClampToBorder);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
TileProvider::~TileProvider(){
|
||||
clearRequestQueue();
|
||||
}
|
||||
|
||||
|
||||
void TileProvider::prerender() {
|
||||
//_rawTextureTileDataProvider.updateAsyncRequests();
|
||||
initTexturesFromLoadedData();
|
||||
|
||||
if (_framesSinceLastRequestFlush++ > _framesUntilRequestFlush) {
|
||||
clearRequestQueue();
|
||||
}
|
||||
}
|
||||
|
||||
void TileProvider::initTexturesFromLoadedData() {
|
||||
while (_tileLoadManager.numFinishedJobs() > 0) {
|
||||
std::shared_ptr<TileIOResult> tileIOResult= _tileLoadManager.popFinishedJob()->product();
|
||||
while (_asyncTextureDataProvider->hasLoadedTextureData()) {
|
||||
std::shared_ptr<TileIOResult> tileIOResult = _asyncTextureDataProvider->nextTileIOResult();
|
||||
initializeAndAddToCache(tileIOResult);
|
||||
}
|
||||
/*
|
||||
while (_rawTextureTileDataProvider.hasTextureTileData()) {
|
||||
auto rawTextureTile = _rawTextureTileDataProvider.nextTextureTile();
|
||||
initializeAndAddToCache(rawTextureTile);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void TileProvider::clearRequestQueue() {
|
||||
_tileLoadManager.clearEnqueuedJobs();
|
||||
_queuedTileRequests.clear();
|
||||
_asyncTextureDataProvider->clearRequestQueue();
|
||||
_framesSinceLastRequestFlush = 0;
|
||||
}
|
||||
|
||||
|
||||
Tile TileProvider::getHighestResolutionTile(ChunkIndex chunkIndex) {
|
||||
TileUvTransform uvTransform;
|
||||
uvTransform.uvOffset = glm::vec2(0, 0);
|
||||
uvTransform.uvScale = glm::vec2(1, 1);
|
||||
|
||||
int maximumLevel = _rawTextureTileDataProvider.getMaximumLevel();
|
||||
Tile TileProvider::getHighestResolutionTile(ChunkIndex chunkIndex, int parents, TileUvTransform uvTransform) {
|
||||
for (int i = 0; i < parents && chunkIndex.level > 1; i++) {
|
||||
transformFromParent(chunkIndex, uvTransform);
|
||||
chunkIndex = chunkIndex.parent();
|
||||
}
|
||||
|
||||
int maximumLevel = _asyncTextureDataProvider->getTextureDataProvider()->getMaximumLevel();
|
||||
while(chunkIndex.level > maximumLevel){
|
||||
transformFromParent(chunkIndex, uvTransform);
|
||||
chunkIndex = chunkIndex.parent();
|
||||
@@ -130,13 +99,14 @@ namespace openspace {
|
||||
Tile TileProvider::getOrEnqueueHighestResolutionTile(const ChunkIndex& chunkIndex,
|
||||
TileUvTransform& uvTransform)
|
||||
{
|
||||
|
||||
HashKey key = chunkIndex.hashKey();
|
||||
|
||||
if (_tileCache.exist(key) && _tileCache.get(key).ioError == CPLErr::CE_None) {
|
||||
std::shared_ptr<Texture> texture = _tileCache.get(key).texture;
|
||||
return { texture, uvTransform };
|
||||
return { _tileCache.get(key).texture, uvTransform };
|
||||
}
|
||||
else if (chunkIndex.level <= 1) {
|
||||
return { getDefaultTexture(), uvTransform };
|
||||
else if (chunkIndex.level < 1) {
|
||||
return { nullptr, uvTransform };
|
||||
}
|
||||
else {
|
||||
// We don't have the tile for the requested level
|
||||
@@ -146,7 +116,7 @@ namespace openspace {
|
||||
|
||||
// As we didn't have this tile, push it to the request queue
|
||||
// post order enqueueing tiles --> enqueue tiles at low levels first
|
||||
enqueueTileRequest(chunkIndex);
|
||||
_asyncTextureDataProvider->enqueueTextureData(chunkIndex);
|
||||
|
||||
return tile;
|
||||
}
|
||||
@@ -175,51 +145,16 @@ namespace openspace {
|
||||
return _tileCache.get(hashkey).texture;
|
||||
}
|
||||
else {
|
||||
enqueueTileRequest(chunkIndex);
|
||||
_asyncTextureDataProvider->enqueueTextureData(chunkIndex);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool TileProvider::enqueueTileRequest(const ChunkIndex& chunkIndex) {
|
||||
HashKey key = chunkIndex.hashKey();
|
||||
auto it = _queuedTileRequests.begin();
|
||||
auto end = _queuedTileRequests.end();
|
||||
for (; it != end; it++) {
|
||||
const ChunkIndex& otherChunk = it->second;
|
||||
if (chunkIndex.level == otherChunk.level &&
|
||||
chunkIndex.manhattan(otherChunk) < 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<TextureTileLoadJob> job = std::shared_ptr<TextureTileLoadJob>(
|
||||
new TextureTileLoadJob(this, chunkIndex));
|
||||
_tileLoadManager.enqueueJob(job);
|
||||
_queuedTileRequests[key] = chunkIndex;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::shared_ptr<Texture> TileProvider::getDefaultTexture() {
|
||||
return _defaultTexture;
|
||||
}
|
||||
|
||||
TileDepthTransform TileProvider::depthTransform() {
|
||||
return _rawTextureTileDataProvider.getDepthTransform();
|
||||
return _asyncTextureDataProvider->getTextureDataProvider()->getDepthTransform();
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<TileIOResult> TileProvider::syncDownloadData(
|
||||
const ChunkIndex& chunkIndex) {
|
||||
|
||||
std::shared_ptr<TileIOResult> res = _rawTextureTileDataProvider.getTextureData(chunkIndex);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void TileProvider::initializeAndAddToCache(std::shared_ptr<TileIOResult> tileIOResult) {
|
||||
|
||||
std::shared_ptr<RawTileData> tileData = tileIOResult->rawTileData;
|
||||
|
||||
@@ -37,8 +37,7 @@
|
||||
|
||||
#include <modules/globebrowsing/geodetics/geodetic2.h>
|
||||
#include <modules/globebrowsing/other/lrucache.h>
|
||||
#include <modules/globebrowsing/other/concurrentjobmanager.h>
|
||||
#include <modules/globebrowsing/other/texturedataprovider.h>
|
||||
#include <modules/globebrowsing/other/asynctilereader.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TILE PROVIDER //
|
||||
@@ -47,76 +46,68 @@
|
||||
namespace openspace {
|
||||
using namespace ghoul::opengl;
|
||||
|
||||
|
||||
|
||||
|
||||
struct TileUvTransform
|
||||
{
|
||||
glm::vec2 uvOffset;
|
||||
glm::vec2 uvScale;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
struct Tile {
|
||||
std::shared_ptr<Texture> texture;
|
||||
TileUvTransform uvTransform;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct MetaTexture {
|
||||
std::shared_ptr<Texture> texture;
|
||||
CPLErr ioError;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Provides tiles through GDAL datasets which can be defined with xml files
|
||||
for example for wms.
|
||||
*/
|
||||
class TileProvider {
|
||||
public:
|
||||
TileProvider(const std::string& fileName, int tileCacheSize, int minimumPixelSize,
|
||||
int framesUntilRequestFlush);
|
||||
|
||||
TileProvider(std::shared_ptr<AsyncTileDataProvider> tileReader, int tileCacheSize,
|
||||
int framesUntilFlushRequestQueue);
|
||||
|
||||
~TileProvider();
|
||||
|
||||
Tile getHighestResolutionTile(ChunkIndex chunkIndex);
|
||||
|
||||
Tile getHighestResolutionTile(ChunkIndex chunkIndex, int parents = 0,
|
||||
TileUvTransform uvTransform = { glm::vec2(0, 0), glm::vec2(1, 1)});
|
||||
|
||||
std::shared_ptr<Texture> getOrStartFetchingTile(ChunkIndex chunkIndex);
|
||||
std::shared_ptr<Texture> getDefaultTexture();
|
||||
TileDepthTransform depthTransform();
|
||||
|
||||
void prerender();
|
||||
|
||||
static ThreadPool threadPool;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
friend class TextureTileLoadJob;
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Helper functions //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
Tile getOrEnqueueHighestResolutionTile(const ChunkIndex& ci, TileUvTransform& uvTransform);
|
||||
Tile getOrEnqueueHighestResolutionTile(const ChunkIndex& ci,
|
||||
TileUvTransform& uvTransform);
|
||||
|
||||
std::shared_ptr<Texture> getOrStartFetchingTile(ChunkIndex chunkIndex);
|
||||
|
||||
|
||||
void transformFromParent(const ChunkIndex& ci, TileUvTransform& uv) const;
|
||||
|
||||
/**
|
||||
Fetches all the needeed texture data from the GDAL dataset.
|
||||
*/
|
||||
std::shared_ptr<TileIOResult> syncDownloadData(
|
||||
const ChunkIndex& chunkIndex);
|
||||
|
||||
|
||||
/**
|
||||
Creates an OpenGL texture and pushes the data to the GPU.
|
||||
*/
|
||||
void initializeAndAddToCache(
|
||||
std::shared_ptr<TileIOResult> uninitedTexture);
|
||||
|
||||
bool enqueueTileRequest(const ChunkIndex& ci);
|
||||
void initializeAndAddToCache(std::shared_ptr<TileIOResult> uninitedTexture);
|
||||
|
||||
void clearRequestQueue();
|
||||
|
||||
@@ -124,27 +115,17 @@ namespace openspace {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Member variables //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LRUCache<HashKey, MetaTexture> _tileCache;
|
||||
std::unordered_map<HashKey, ChunkIndex> _queuedTileRequests;
|
||||
|
||||
int _framesSinceLastRequestFlush;
|
||||
int _framesUntilRequestFlush;
|
||||
|
||||
const std::string _filePath;
|
||||
|
||||
|
||||
TextureDataProvider _rawTextureTileDataProvider;
|
||||
|
||||
ConcurrentJobManager<TileIOResult> _tileLoadManager;
|
||||
|
||||
std::shared_ptr<Texture> _defaultTexture;
|
||||
|
||||
std::shared_ptr<AsyncTileDataProvider> _asyncTextureDataProvider;
|
||||
};
|
||||
|
||||
|
||||
@@ -155,38 +136,4 @@ namespace openspace {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
namespace openspace {
|
||||
|
||||
using namespace ghoul::opengl;
|
||||
|
||||
struct TextureTileLoadJob : public Job<TileIOResult> {
|
||||
TextureTileLoadJob(TileProvider * tileProvider, const ChunkIndex& chunkIndex)
|
||||
: _tileProvider(tileProvider)
|
||||
, _chunkIndex(chunkIndex) {
|
||||
|
||||
}
|
||||
|
||||
virtual ~TextureTileLoadJob() { }
|
||||
|
||||
virtual void execute() {
|
||||
_uninitedTexture = _tileProvider->syncDownloadData(_chunkIndex);
|
||||
}
|
||||
|
||||
virtual std::shared_ptr<TileIOResult> product() {
|
||||
return _uninitedTexture;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
ChunkIndex _chunkIndex;
|
||||
TileProvider * _tileProvider;
|
||||
std::shared_ptr<TileIOResult> _uninitedTexture;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __TILE_PROVIDER_H__
|
||||
File diff suppressed because it is too large
Load Diff
@@ -34,10 +34,9 @@
|
||||
#include <modules/globebrowsing/geodetics/geodetic2.h>
|
||||
#include <modules/globebrowsing/geodetics/ellipsoid.h>
|
||||
#include <modules/globebrowsing/meshes/grid.h>
|
||||
#include <modules/globebrowsing/meshes/clipmapgrid.h>
|
||||
//#include <modules/globebrowsing/rendering/frustumculler.h>
|
||||
#include <modules/globebrowsing/other/patchcoverageprovider.h>
|
||||
#include <modules/globebrowsing/other/tileprovidermanager.h>
|
||||
|
||||
#include <modules/globebrowsing/other/layeredtextureshaderprovider.h>
|
||||
#include <modules/globebrowsing/globes/chunknode.h>
|
||||
|
||||
@@ -95,35 +94,6 @@ namespace openspace {
|
||||
|
||||
|
||||
|
||||
class ClipMapPatchRenderer : public PatchRenderer {
|
||||
public:
|
||||
ClipMapPatchRenderer(
|
||||
shared_ptr<ClipMapGrid> grid,
|
||||
shared_ptr<TileProviderManager> tileProviderManager);
|
||||
|
||||
~ClipMapPatchRenderer();
|
||||
|
||||
void renderPatch(
|
||||
const Geodetic2& patchSize,
|
||||
const RenderData& data,
|
||||
const Ellipsoid& ellipsoid);
|
||||
private:
|
||||
|
||||
void renderPatchGlobally(
|
||||
const Geodetic2& patchSize,
|
||||
const RenderData& data,
|
||||
const Ellipsoid& ellipsoid);
|
||||
void renderPatchLocally(
|
||||
const Geodetic2& patchSize,
|
||||
const RenderData& data,
|
||||
const Ellipsoid& ellipsoid);
|
||||
|
||||
unique_ptr<ProgramObject> _programObjectGlobalRendering;
|
||||
unique_ptr<ProgramObject> _programObjectLocalRendering;
|
||||
|
||||
PatchCoverageProvider _patchCoverageProvider;
|
||||
shared_ptr<ClipMapGrid> _grid;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
|
||||
@@ -31,31 +31,43 @@
|
||||
#define NUMLAYERS_HEIGHTMAP #{numLayersHeight}
|
||||
|
||||
uniform TextureTile colorTiles[NUMLAYERS_COLORTEXTURE];
|
||||
uniform TextureTile colorTilesParent1[NUMLAYERS_COLORTEXTURE];
|
||||
uniform TextureTile colorTilesParent2[NUMLAYERS_COLORTEXTURE];
|
||||
|
||||
in vec4 fs_position;
|
||||
in vec2 fs_uv;
|
||||
|
||||
in float tileInterpolationParameter;
|
||||
|
||||
Fragment getFragment() {
|
||||
Fragment frag;
|
||||
|
||||
#for i in 0..#{numLayersColor}
|
||||
// tileInterpolationParameter increases with distance
|
||||
float w1 = clamp(1 - tileInterpolationParameter, 0 , 1);
|
||||
float w2 = (clamp(tileInterpolationParameter, 0 , 1) - clamp(tileInterpolationParameter - 1, 0 , 1));
|
||||
float w3 = clamp(tileInterpolationParameter - 1, 0 , 1);
|
||||
|
||||
#for j in 1..#{numLayersColor}
|
||||
{
|
||||
int i = #{j} - 1;
|
||||
vec2 samplePos =
|
||||
colorTiles[#{i}].uvTransform.uvScale * fs_uv +
|
||||
colorTiles[#{i}].uvTransform.uvOffset;
|
||||
vec4 colorSample = texture(colorTiles[#{i}].textureSampler, samplePos);
|
||||
colorTiles[i].uvTransform.uvScale * fs_uv +
|
||||
colorTiles[i].uvTransform.uvOffset;
|
||||
vec2 samplePosParent1 =
|
||||
colorTilesParent1[i].uvTransform.uvScale * fs_uv +
|
||||
colorTilesParent1[i].uvTransform.uvOffset;
|
||||
vec2 samplePosParent2 =
|
||||
colorTilesParent2[i].uvTransform.uvScale * fs_uv +
|
||||
colorTilesParent2[i].uvTransform.uvOffset;
|
||||
|
||||
vec4 colorSample =
|
||||
w1 * texture(colorTiles[i].textureSampler, samplePos) +
|
||||
w2 * texture(colorTilesParent1[i].textureSampler, samplePosParent1) +
|
||||
w3 * texture(colorTilesParent2[i].textureSampler, samplePosParent2);
|
||||
frag.color = blendOver(frag.color, colorSample);
|
||||
}
|
||||
#endfor
|
||||
|
||||
//frag.color.rgb *= 10;
|
||||
|
||||
// Sample position overlay
|
||||
//frag.color = frag.color * 0.9 + 0.2*vec4(samplePos, 0, 1);
|
||||
|
||||
// Border overlay
|
||||
//frag.color = frag.color + patchBorderOverlay(fs_uv, vec3(0.5, 0.5, 0.5), 0.02);
|
||||
|
||||
frag.depth = fs_position.w;
|
||||
|
||||
return frag;
|
||||
|
||||
@@ -37,12 +37,24 @@ uniform vec3 radiiSquared;
|
||||
uniform vec2 minLatLon;
|
||||
uniform vec2 lonLatScalingFactor;
|
||||
|
||||
uniform int xSegments;
|
||||
uniform float skirtLength;
|
||||
|
||||
uniform TextureTile heightTiles[NUMLAYERS_HEIGHTMAP];
|
||||
uniform TextureTile heightTilesParent1[NUMLAYERS_HEIGHTMAP];
|
||||
uniform TextureTile heightTilesParent2[NUMLAYERS_HEIGHTMAP];
|
||||
|
||||
uniform vec3 cameraPosition;
|
||||
uniform float distanceScaleFactor;
|
||||
uniform int chunkLevel;
|
||||
|
||||
layout(location = 1) in vec2 in_uv;
|
||||
|
||||
out vec2 fs_uv;
|
||||
out vec4 fs_position;
|
||||
// tileInterpolationParameter 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
|
||||
out float tileInterpolationParameter;
|
||||
|
||||
PositionNormalPair globalInterpolation() {
|
||||
vec2 lonLatInput;
|
||||
@@ -58,18 +70,49 @@ void main()
|
||||
|
||||
float height = 0;
|
||||
|
||||
#for i in 0..#{numLayersHeight}
|
||||
{
|
||||
vec2 samplePos =
|
||||
heightTiles[#{i}].uvTransform.uvScale * in_uv +
|
||||
heightTiles[#{i}].uvTransform.uvOffset;
|
||||
// Calculate desired level based on distance to the vertex on the ellipsoid
|
||||
// Before any heightmapping is done
|
||||
float distToVertexOnEllipsoid = length(pair.position - cameraPosition);
|
||||
float projectedScaleFactor = distanceScaleFactor / distToVertexOnEllipsoid;
|
||||
float desiredLevel = log2(projectedScaleFactor);
|
||||
|
||||
float sampledValue = texture(heightTiles[#{i}].textureSampler, samplePos).r;
|
||||
tileInterpolationParameter = chunkLevel - desiredLevel;
|
||||
float w1 = clamp(1 - tileInterpolationParameter, 0 , 1);
|
||||
float w2 = (clamp(tileInterpolationParameter, 0 , 1) - clamp(tileInterpolationParameter - 1, 0 , 1));
|
||||
float w3 = clamp(tileInterpolationParameter - 1, 0 , 1);
|
||||
|
||||
#for j in 1..#{numLayersHeight}
|
||||
{
|
||||
int i = #{j} - 1;
|
||||
vec2 samplePos =
|
||||
heightTiles[i].uvTransform.uvScale * in_uv +
|
||||
heightTiles[i].uvTransform.uvOffset;
|
||||
vec2 samplePosParent1 =
|
||||
heightTilesParent1[i].uvTransform.uvScale * in_uv +
|
||||
heightTilesParent1[i].uvTransform.uvOffset;
|
||||
vec2 samplePosParent2 =
|
||||
heightTilesParent2[i].uvTransform.uvScale * in_uv +
|
||||
heightTilesParent2[i].uvTransform.uvOffset;
|
||||
|
||||
float sampledValue =
|
||||
w1 * texture(heightTiles[i].textureSampler, samplePos).r +
|
||||
w2 * texture(heightTilesParent1[i].textureSampler, samplePosParent1).r +
|
||||
w3 * texture(heightTilesParent2[i].textureSampler, samplePosParent2).r;
|
||||
|
||||
// TODO : Some kind of blending here. Now it just writes over
|
||||
height = (sampledValue *
|
||||
heightTiles[#{i}].depthTransform.depthScale +
|
||||
heightTiles[#{i}].depthTransform.depthOffset);
|
||||
heightTiles[i].depthTransform.depthScale +
|
||||
heightTiles[i].depthTransform.depthOffset);
|
||||
|
||||
// Skirts
|
||||
int vertexIDx = gl_VertexID % (xSegments + 3);
|
||||
int vertexIDy = gl_VertexID / (xSegments + 3);
|
||||
if (vertexIDx == 0 ||
|
||||
vertexIDy == 0 ||
|
||||
vertexIDx == (xSegments + 2) ||
|
||||
vertexIDy == (xSegments + 2) ) {
|
||||
height -= skirtLength;
|
||||
}
|
||||
}
|
||||
#endfor
|
||||
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014 *
|
||||
* *
|
||||
* 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. *
|
||||
****************************************************************************************/
|
||||
|
||||
/*
|
||||
// Heightmap coverage
|
||||
uniform sampler2D textureSamplerHeight00;
|
||||
uniform sampler2D textureSamplerHeight10;
|
||||
uniform sampler2D textureSamplerHeight01;
|
||||
uniform sampler2D textureSamplerHeight11;
|
||||
uniform mat3 uvTransformPatchToTileHeight00;
|
||||
uniform mat3 uvTransformPatchToTileHeight10;
|
||||
uniform mat3 uvTransformPatchToTileHeight01;
|
||||
uniform mat3 uvTransformPatchToTileHeight11;
|
||||
*/
|
||||
|
||||
// Colortexture coverage
|
||||
uniform sampler2D textureSamplerColor00;
|
||||
uniform sampler2D textureSamplerColor10;
|
||||
uniform sampler2D textureSamplerColor01;
|
||||
uniform sampler2D textureSamplerColor11;
|
||||
uniform mat3 uvTransformPatchToTileColor00;
|
||||
uniform mat3 uvTransformPatchToTileColor10;
|
||||
uniform mat3 uvTransformPatchToTileColor01;
|
||||
uniform mat3 uvTransformPatchToTileColor11;
|
||||
uniform uvec2 texture00DimensionsColor;
|
||||
uniform uvec2 texture10DimensionsColor;
|
||||
uniform uvec2 texture01DimensionsColor;
|
||||
uniform uvec2 texture11DimensionsColor;
|
||||
|
||||
//uniform int segmentsPerPatch;
|
||||
|
||||
in vec4 vs_position;
|
||||
in vec3 fs_position;
|
||||
in vec2 fs_uv;
|
||||
|
||||
#include "PowerScaling/powerScaling_fs.hglsl"
|
||||
#include "fragment.glsl"
|
||||
|
||||
Fragment getFragment() {
|
||||
Fragment frag;
|
||||
|
||||
frag.color = vec4(0);
|
||||
vec4 color00, color10, color01, color11;
|
||||
|
||||
vec2 uv00 = vec2(uvTransformPatchToTileColor00 * vec3(fs_uv.s, fs_uv.t, 1));
|
||||
vec2 uv10 = vec2(uvTransformPatchToTileColor10 * vec3(fs_uv.s, fs_uv.t, 1));
|
||||
vec2 uv01 = vec2(uvTransformPatchToTileColor01 * vec3(fs_uv.s, fs_uv.t, 1));
|
||||
vec2 uv11 = vec2(uvTransformPatchToTileColor11 * vec3(fs_uv.s, fs_uv.t, 1));
|
||||
|
||||
vec2 d00 = 1 / vec2(texture00DimensionsColor);
|
||||
vec2 d10 = 1 / vec2(texture10DimensionsColor);
|
||||
vec2 d01 = 1 / vec2(texture01DimensionsColor);
|
||||
vec2 d11 = 1 / vec2(texture11DimensionsColor);
|
||||
|
||||
if (uv00.x > -d00.x && uv00.x < 1 + d00.x && uv00.y > -d00.y && uv00.y < 1 + d00.y)
|
||||
color00 = texture(textureSamplerColor00, uv00);
|
||||
if (uv10.x > -d10.x && uv10.x < 1 + d10.x && uv10.y > -d10.y && uv10.y < 1 + d10.y)
|
||||
color10 = texture(textureSamplerColor10, uv10);
|
||||
if (uv01.x > -d01.x && uv01.x < 1 + d01.x && uv01.y > -d01.y && uv01.y < 1 + d01.y)
|
||||
color01 = texture(textureSamplerColor01, uv01);
|
||||
if (uv11.x > -d11.x && uv11.x < 1 + d11.x && uv11.y > -d11.y && uv11.y < 1 + d11.y)
|
||||
color11 = texture(textureSamplerColor11, uv11);
|
||||
|
||||
frag.color = max(color00, max(color10, max(color01, color11)));
|
||||
//frag.color = vec4(frag.color.r, frag.color.r, frag.color.r, 1);
|
||||
|
||||
frag.depth = vs_position.w;
|
||||
|
||||
return frag;
|
||||
}
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014 *
|
||||
* *
|
||||
* 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__
|
||||
|
||||
uniform mat4 modelViewProjectionTransform;
|
||||
uniform vec3 radiiSquared;
|
||||
|
||||
uniform vec2 minLatLon;
|
||||
uniform vec2 lonLatScalingFactor;
|
||||
uniform ivec2 contraction; // [-1, 1]
|
||||
|
||||
uniform int segmentsPerPatch;
|
||||
|
||||
uniform sampler2D textureSamplerHeight00;
|
||||
uniform sampler2D textureSamplerHeight10;
|
||||
uniform sampler2D textureSamplerHeight01;
|
||||
uniform sampler2D textureSamplerHeight11;
|
||||
uniform mat3 uvTransformPatchToTileHeight00;
|
||||
uniform mat3 uvTransformPatchToTileHeight10;
|
||||
uniform mat3 uvTransformPatchToTileHeight01;
|
||||
uniform mat3 uvTransformPatchToTileHeight11;
|
||||
uniform uvec2 texture00DimensionsHeight;
|
||||
uniform uvec2 texture10DimensionsHeight;
|
||||
uniform uvec2 texture01DimensionsHeight;
|
||||
uniform uvec2 texture11DimensionsHeight;
|
||||
|
||||
layout(location = 1) in vec2 in_uv;
|
||||
|
||||
out vec4 vs_position;
|
||||
out vec3 fs_position;
|
||||
out vec2 fs_uv;
|
||||
|
||||
|
||||
#include "PowerScaling/powerScaling_vs.hglsl"
|
||||
#include <${MODULE_GLOBEBROWSING}/shaders/ellipsoid.hglsl>
|
||||
|
||||
PositionNormalPair globalInterpolation(vec2 uv) {
|
||||
vec2 lonLatInput;
|
||||
lonLatInput.y = minLatLon.y + lonLatScalingFactor.y * uv.y; // Lat
|
||||
lonLatInput.x = minLatLon.x + lonLatScalingFactor.x * uv.x; // Lon
|
||||
return geodetic2ToCartesian(lonLatInput.y, lonLatInput.x, radiiSquared);;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
fs_uv = in_uv;
|
||||
|
||||
// Contract
|
||||
vec2 scaledContraction = contraction / float(segmentsPerPatch);
|
||||
fs_uv += scaledContraction;
|
||||
fs_uv = clamp(fs_uv, 0, 1);
|
||||
fs_uv -= scaledContraction;
|
||||
|
||||
PositionNormalPair pair = globalInterpolation(fs_uv);
|
||||
|
||||
float sampledHeight00 = 0;
|
||||
float sampledHeight10 = 0;
|
||||
float sampledHeight01 = 0;
|
||||
float sampledHeight11 = 0;
|
||||
|
||||
vec2 uv00 = vec2(uvTransformPatchToTileHeight00 * vec3(fs_uv.s, fs_uv.t, 1));
|
||||
vec2 uv10 = vec2(uvTransformPatchToTileHeight10 * vec3(fs_uv.s, fs_uv.t, 1));
|
||||
vec2 uv01 = vec2(uvTransformPatchToTileHeight01 * vec3(fs_uv.s, fs_uv.t, 1));
|
||||
vec2 uv11 = vec2(uvTransformPatchToTileHeight11 * vec3(fs_uv.s, fs_uv.t, 1));
|
||||
|
||||
vec2 d00 = vec2(1,1) / texture00DimensionsHeight;
|
||||
vec2 d10 = vec2(1,1) / texture10DimensionsHeight;
|
||||
vec2 d01 = vec2(1,1) / texture01DimensionsHeight;
|
||||
vec2 d11 = vec2(1,1) / texture11DimensionsHeight;
|
||||
|
||||
if (uv00.x > -d00.x && uv00.x < 1 + d00.x && uv00.y > -d00.y && uv00.y < 1 + d00.y)
|
||||
sampledHeight00 = texture(textureSamplerHeight00, uv00).r;
|
||||
if (uv10.x > -d10.x && uv10.x < 1 + d10.x && uv10.y > -d10.y && uv10.y < 1 + d10.y)
|
||||
sampledHeight10 = texture(textureSamplerHeight10, uv10).r;
|
||||
if (uv01.x > -d01.x && uv01.x < 1 + d01.x && uv01.y > -d01.y && uv01.y < 1 + d01.y)
|
||||
sampledHeight01 = texture(textureSamplerHeight01, uv01).r;
|
||||
if (uv11.x > -d11.x && uv11.x < 1 + d11.x && uv11.y > -d11.y && uv11.y < 1 + d11.y)
|
||||
sampledHeight11 = texture(textureSamplerHeight11, uv11).r;
|
||||
|
||||
|
||||
|
||||
float sampledHeight = max(sampledHeight00, max(sampledHeight10, max(sampledHeight01, sampledHeight11)));
|
||||
|
||||
pair.position += pair.normal * sampledHeight * pow(2,15);
|
||||
|
||||
vec4 position = modelViewProjectionTransform * vec4(pair.position, 1);
|
||||
fs_position = pair.position;
|
||||
|
||||
gl_Position = z_normalization(position);
|
||||
vs_position = gl_Position;
|
||||
}
|
||||
@@ -31,6 +31,12 @@
|
||||
#define NUMLAYERS_HEIGHTMAP #{numLayersHeight}
|
||||
|
||||
uniform TextureTile colorTiles[NUMLAYERS_COLORTEXTURE];
|
||||
uniform TextureTile colorTilesParent1[NUMLAYERS_COLORTEXTURE];
|
||||
uniform TextureTile colorTilesParent2[NUMLAYERS_COLORTEXTURE];
|
||||
|
||||
// tileInterpolationParameter 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 float tileInterpolationParameter;
|
||||
|
||||
in vec4 fs_position;
|
||||
in vec2 fs_uv;
|
||||
@@ -38,29 +44,33 @@ in vec2 fs_uv;
|
||||
Fragment getFragment() {
|
||||
Fragment frag;
|
||||
|
||||
#for i in 0..#{numLayersColor}
|
||||
// tileInterpolationParameter increases with distance to camera
|
||||
float w1 = clamp(1 - tileInterpolationParameter, 0 , 1);
|
||||
float w2 = (clamp(tileInterpolationParameter, 0 , 1) - clamp(tileInterpolationParameter - 1, 0 , 1));
|
||||
float w3 = clamp(tileInterpolationParameter - 1, 0 , 1);
|
||||
|
||||
#for j in 1..#{numLayersColor}
|
||||
{
|
||||
int i = #{j} - 1;
|
||||
|
||||
vec2 samplePos =
|
||||
colorTiles[#{i}].uvTransform.uvScale * fs_uv +
|
||||
colorTiles[#{i}].uvTransform.uvOffset;
|
||||
vec4 colorSample = texture(colorTiles[#{i}].textureSampler, samplePos);
|
||||
colorTiles[i].uvTransform.uvScale * fs_uv +
|
||||
colorTiles[i].uvTransform.uvOffset;
|
||||
vec2 samplePosParent1 =
|
||||
colorTilesParent1[i].uvTransform.uvScale * fs_uv +
|
||||
colorTilesParent1[i].uvTransform.uvOffset;
|
||||
vec2 samplePosParent2 =
|
||||
colorTilesParent2[i].uvTransform.uvScale * fs_uv +
|
||||
colorTilesParent2[i].uvTransform.uvOffset;
|
||||
|
||||
vec4 colorSample =
|
||||
w1 * texture(colorTiles[i].textureSampler, samplePos) +
|
||||
w2 * texture(colorTilesParent1[i].textureSampler, samplePosParent1) +
|
||||
w3 * texture(colorTilesParent2[i].textureSampler, samplePosParent2);
|
||||
frag.color = blendOver(frag.color, colorSample);
|
||||
}
|
||||
#endfor
|
||||
|
||||
//vec2 samplePos =
|
||||
// colorTile.uvTransform.uvScale * fs_uv +
|
||||
// colorTile.uvTransform.uvOffset;
|
||||
//frag.color = texture(colorTile.textureSampler, samplePos);
|
||||
|
||||
//frag.color.rgb *= 10;
|
||||
|
||||
// Sample position overlay
|
||||
//frag.color = frag.color * 0.9 + 0.2*vec4(samplePos, 0, 1);
|
||||
|
||||
// Border overlay
|
||||
//frag.color = frag.color + patchBorderOverlay(fs_uv, vec3(0.5, 0.5, 0.5), 0.02);
|
||||
|
||||
frag.depth = fs_position.w;
|
||||
|
||||
return frag;
|
||||
|
||||
@@ -41,11 +41,22 @@ uniform vec3 p11;
|
||||
uniform vec3 patchNormalCameraSpace;
|
||||
|
||||
uniform TextureTile heightTiles[NUMLAYERS_HEIGHTMAP];
|
||||
uniform TextureTile heightTilesParent1[NUMLAYERS_HEIGHTMAP];
|
||||
uniform TextureTile heightTilesParent2[NUMLAYERS_HEIGHTMAP];
|
||||
|
||||
uniform int xSegments;
|
||||
uniform float skirtLength;
|
||||
|
||||
uniform float distanceScaleFactor;
|
||||
uniform int chunkLevel;
|
||||
|
||||
layout(location = 1) in vec2 in_uv;
|
||||
|
||||
out vec2 fs_uv;
|
||||
out vec4 fs_position;
|
||||
// tileInterpolationParameter 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
|
||||
out float tileInterpolationParameter;
|
||||
|
||||
vec3 bilinearInterpolation(vec2 uv) {
|
||||
// Bilinear interpolation
|
||||
@@ -62,18 +73,49 @@ void main()
|
||||
|
||||
float height = 0;
|
||||
|
||||
#for i in 0..#{numLayersHeight}
|
||||
{
|
||||
vec2 samplePos =
|
||||
heightTiles[#{i}].uvTransform.uvScale * in_uv +
|
||||
heightTiles[#{i}].uvTransform.uvOffset;
|
||||
// Calculate desired level based on distance to the vertex on the ellipsoid
|
||||
// Before any heightmapping is done
|
||||
float distToVertexOnEllipsoid = length(p);
|
||||
float projectedScaleFactor = distanceScaleFactor / distToVertexOnEllipsoid;
|
||||
float desiredLevel = log2(projectedScaleFactor);
|
||||
|
||||
float sampledValue = texture(heightTiles[#{i}].textureSampler, samplePos).r;
|
||||
tileInterpolationParameter = chunkLevel - desiredLevel;
|
||||
float w1 = clamp(1 - tileInterpolationParameter, 0 , 1);
|
||||
float w2 = (clamp(tileInterpolationParameter, 0 , 1) - clamp(tileInterpolationParameter - 1, 0 , 1));
|
||||
float w3 = clamp(tileInterpolationParameter - 1, 0 , 1);
|
||||
|
||||
#for j in 1..#{numLayersHeight}
|
||||
{
|
||||
int i = #{j} - 1;
|
||||
vec2 samplePos =
|
||||
heightTiles[i].uvTransform.uvScale * in_uv +
|
||||
heightTiles[i].uvTransform.uvOffset;
|
||||
vec2 samplePosParent1 =
|
||||
heightTilesParent1[i].uvTransform.uvScale * in_uv +
|
||||
heightTilesParent1[i].uvTransform.uvOffset;
|
||||
vec2 samplePosParent2 =
|
||||
heightTilesParent2[i].uvTransform.uvScale * in_uv +
|
||||
heightTilesParent2[i].uvTransform.uvOffset;
|
||||
|
||||
float sampledValue =
|
||||
w1 * texture(heightTiles[i].textureSampler, samplePos).r +
|
||||
w2 * texture(heightTilesParent1[i].textureSampler, samplePosParent1).r +
|
||||
w3 * texture(heightTilesParent2[i].textureSampler, samplePosParent2).r;
|
||||
|
||||
// TODO : Some kind of blending here. Now it just writes over
|
||||
height = (sampledValue *
|
||||
heightTiles[#{i}].depthTransform.depthScale +
|
||||
heightTiles[#{i}].depthTransform.depthOffset);
|
||||
heightTiles[i].depthTransform.depthScale +
|
||||
heightTiles[i].depthTransform.depthOffset);
|
||||
|
||||
// Skirts
|
||||
int vertexIDx = gl_VertexID % (xSegments + 3);
|
||||
int vertexIDy = gl_VertexID / (xSegments + 3);
|
||||
if (vertexIDx == 0 ||
|
||||
vertexIDy == 0 ||
|
||||
vertexIDx == (xSegments + 2) ||
|
||||
vertexIDy == (xSegments + 2) ) {
|
||||
height -= skirtLength;
|
||||
}
|
||||
}
|
||||
#endfor
|
||||
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014 *
|
||||
* *
|
||||
* 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. *
|
||||
****************************************************************************************/
|
||||
|
||||
/*
|
||||
// Heightmap coverage
|
||||
uniform sampler2D textureSamplerHeight00;
|
||||
uniform sampler2D textureSamplerHeight10;
|
||||
uniform sampler2D textureSamplerHeight01;
|
||||
uniform sampler2D textureSamplerHeight11;
|
||||
uniform mat3 uvTransformPatchToTileHeight00;
|
||||
uniform mat3 uvTransformPatchToTileHeight10;
|
||||
uniform mat3 uvTransformPatchToTileHeight01;
|
||||
uniform mat3 uvTransformPatchToTileHeight11;
|
||||
*/
|
||||
|
||||
// Colortexture coverage
|
||||
uniform sampler2D textureSamplerColor00;
|
||||
uniform sampler2D textureSamplerColor10;
|
||||
uniform sampler2D textureSamplerColor01;
|
||||
uniform sampler2D textureSamplerColor11;
|
||||
uniform mat3 uvTransformPatchToTileColor00;
|
||||
uniform mat3 uvTransformPatchToTileColor10;
|
||||
uniform mat3 uvTransformPatchToTileColor01;
|
||||
uniform mat3 uvTransformPatchToTileColor11;
|
||||
uniform uvec2 texture00DimensionsColor;
|
||||
uniform uvec2 texture10DimensionsColor;
|
||||
uniform uvec2 texture01DimensionsColor;
|
||||
uniform uvec2 texture11DimensionsColor;
|
||||
|
||||
//uniform int segmentsPerPatch;
|
||||
|
||||
in vec4 vs_position;
|
||||
in vec3 fs_position;
|
||||
in vec2 fs_uv;
|
||||
|
||||
#include "PowerScaling/powerScaling_fs.hglsl"
|
||||
#include "fragment.glsl"
|
||||
|
||||
Fragment getFragment() {
|
||||
Fragment frag;
|
||||
|
||||
frag.color = vec4(0);
|
||||
vec4 color00, color10, color01, color11;
|
||||
|
||||
vec2 uv00 = vec2(uvTransformPatchToTileColor00 * vec3(fs_uv.s, fs_uv.t, 1));
|
||||
vec2 uv10 = vec2(uvTransformPatchToTileColor10 * vec3(fs_uv.s, fs_uv.t, 1));
|
||||
vec2 uv01 = vec2(uvTransformPatchToTileColor01 * vec3(fs_uv.s, fs_uv.t, 1));
|
||||
vec2 uv11 = vec2(uvTransformPatchToTileColor11 * vec3(fs_uv.s, fs_uv.t, 1));
|
||||
|
||||
vec2 d00 = vec2(1,1) / texture00DimensionsColor;
|
||||
vec2 d10 = vec2(1,1) / texture10DimensionsColor;
|
||||
vec2 d01 = vec2(1,1) / texture01DimensionsColor;
|
||||
vec2 d11 = vec2(1,1) / texture11DimensionsColor;
|
||||
|
||||
if (uv00.x > -d00.x && uv00.x < 1 + d00.x && uv00.y > -d00.y && uv00.y < 1 + d00.y)
|
||||
color00 = texture(textureSamplerColor00, uv00);
|
||||
if (uv10.x > -d10.x && uv10.x < 1 + d10.x && uv10.y > -d10.y && uv10.y < 1 + d10.y)
|
||||
color10 = texture(textureSamplerColor10, uv10);
|
||||
if (uv01.x > -d01.x && uv01.x < 1 + d01.x && uv01.y > -d01.y && uv01.y < 1 + d01.y)
|
||||
color01 = texture(textureSamplerColor01, uv01);
|
||||
if (uv11.x > -d11.x && uv11.x < 1 + d11.x && uv11.y > -d11.y && uv11.y < 1 + d11.y)
|
||||
color11 = texture(textureSamplerColor11, uv11);
|
||||
|
||||
frag.color = max(color00, max(color10, max(color01, color11)));
|
||||
//frag.color = vec4(frag.color.r, frag.color.r, 0, 1);
|
||||
|
||||
frag.depth = vs_position.w;
|
||||
|
||||
return frag;
|
||||
}
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014 *
|
||||
* *
|
||||
* 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__
|
||||
|
||||
uniform mat4 projectionTransform;
|
||||
|
||||
uniform ivec2 contraction; // [-1, 1]
|
||||
|
||||
uniform vec3 p00;
|
||||
uniform vec3 p10;
|
||||
uniform vec3 p01;
|
||||
uniform vec3 p11;
|
||||
uniform vec3 patchNormal;
|
||||
|
||||
uniform int segmentsPerPatch;
|
||||
|
||||
uniform mat3 uvTransformPatchToTileHeight00;
|
||||
uniform mat3 uvTransformPatchToTileHeight10;
|
||||
uniform mat3 uvTransformPatchToTileHeight01;
|
||||
uniform mat3 uvTransformPatchToTileHeight11;
|
||||
uniform sampler2D textureSamplerHeight00;
|
||||
uniform sampler2D textureSamplerHeight10;
|
||||
uniform sampler2D textureSamplerHeight01;
|
||||
uniform sampler2D textureSamplerHeight11;
|
||||
uniform uvec2 texture00DimensionsHeight;
|
||||
uniform uvec2 texture10DimensionsHeight;
|
||||
uniform uvec2 texture01DimensionsHeight;
|
||||
uniform uvec2 texture11DimensionsHeight;
|
||||
|
||||
layout(location = 1) in vec2 in_uv;
|
||||
|
||||
out vec4 vs_position;
|
||||
out vec3 fs_position;
|
||||
out vec2 fs_uv;
|
||||
|
||||
|
||||
#include "PowerScaling/powerScaling_vs.hglsl"
|
||||
#include <${MODULE_GLOBEBROWSING}/shaders/ellipsoid.hglsl>
|
||||
|
||||
vec3 bilinearInterpolation(vec2 uv) {
|
||||
// Bilinear interpolation
|
||||
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;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
fs_uv = in_uv;
|
||||
|
||||
// Contract
|
||||
vec2 scaledContraction = contraction / float(segmentsPerPatch);
|
||||
fs_uv += scaledContraction;
|
||||
fs_uv = clamp(fs_uv, 0, 1);
|
||||
fs_uv -= scaledContraction;
|
||||
|
||||
// Position in cameraspace
|
||||
vec3 p = bilinearInterpolation(fs_uv);
|
||||
|
||||
float sampledHeight00 = 0;
|
||||
float sampledHeight10 = 0;
|
||||
float sampledHeight01 = 0;
|
||||
float sampledHeight11 = 0;
|
||||
|
||||
vec2 uv00 = vec2(uvTransformPatchToTileHeight00 * vec3(fs_uv.s, fs_uv.t, 1));
|
||||
vec2 uv10 = vec2(uvTransformPatchToTileHeight10 * vec3(fs_uv.s, fs_uv.t, 1));
|
||||
vec2 uv01 = vec2(uvTransformPatchToTileHeight01 * vec3(fs_uv.s, fs_uv.t, 1));
|
||||
vec2 uv11 = vec2(uvTransformPatchToTileHeight11 * vec3(fs_uv.s, fs_uv.t, 1));
|
||||
|
||||
vec2 d00 = vec2(1,1) / texture00DimensionsHeight;
|
||||
vec2 d10 = vec2(1,1) / texture10DimensionsHeight;
|
||||
vec2 d01 = vec2(1,1) / texture01DimensionsHeight;
|
||||
vec2 d11 = vec2(1,1) / texture11DimensionsHeight;
|
||||
|
||||
if (uv00.x > -d00.x && uv00.x < 1 + d00.x && uv00.y > -d00.y && uv00.y < 1 + d00.y)
|
||||
sampledHeight00 = texture(textureSamplerHeight00, uv00).r;
|
||||
if (uv10.x > -d10.x && uv10.x < 1 + d10.x && uv10.y > -d10.y && uv10.y < 1 + d10.y)
|
||||
sampledHeight10 = texture(textureSamplerHeight10, uv10).r;
|
||||
if (uv01.x > -d01.x && uv01.x < 1 + d01.x && uv01.y > -d01.y && uv01.y < 1 + d01.y)
|
||||
sampledHeight01 = texture(textureSamplerHeight01, uv01).r;
|
||||
if (uv11.x > -d11.x && uv11.x < 1 + d11.x && uv11.y > -d11.y && uv11.y < 1 + d11.y)
|
||||
sampledHeight11 = texture(textureSamplerHeight11, uv11).r;
|
||||
|
||||
float sampledHeight = max(sampledHeight00, max(sampledHeight10, max(sampledHeight01, sampledHeight11)));
|
||||
|
||||
p += patchNormal * sampledHeight * pow(2,15);
|
||||
|
||||
vec4 position = projectionTransform * vec4(p, 1);
|
||||
fs_position = p;
|
||||
|
||||
gl_Position = z_normalization(position);
|
||||
vs_position = gl_Position;
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014 *
|
||||
* *
|
||||
* 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/texturetile.hglsl>
|
||||
#include "PowerScaling/powerScaling_fs.hglsl"
|
||||
#include "fragment.glsl"
|
||||
|
||||
#define NUMLAYERS_COLORTEXTURE #{numLayersColor}
|
||||
#define NUMLAYERS_HEIGHTMAP #{numLayersHeight}
|
||||
|
||||
uniform TextureTile colorTiles[NUMLAYERS_COLORTEXTURE];
|
||||
|
||||
in vec4 fs_position;
|
||||
in vec2 fs_uv;
|
||||
|
||||
vec4 blendOver(vec4 oldColor, vec4 newColor)
|
||||
{
|
||||
vec4 toReturn;
|
||||
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);
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
Fragment getFragment() {
|
||||
Fragment frag;
|
||||
|
||||
for (int i = 0; i < NUMLAYERS_COLORTEXTURE; ++i)
|
||||
{
|
||||
vec2 samplePos =
|
||||
colorTile.uvTransform.uvScale * fs_uv +
|
||||
colorTile.uvTransform.uvOffset;
|
||||
vec4 colorSample = texture(colorTile.textureSampler, samplePos);
|
||||
frag.color = blendOver(frag.color, colorSample);
|
||||
}
|
||||
|
||||
//frag.color.rgb *= 10;
|
||||
|
||||
// Sample position overlay
|
||||
//frag.color = frag.color * 0.9 + 0.2*vec4(samplePos, 0, 1);
|
||||
|
||||
// Border overlay
|
||||
//frag.color = frag.color + patchBorderOverlay(fs_uv, vec3(0.5, 0.5, 0.5), 0.02);
|
||||
|
||||
frag.depth = fs_position.w;
|
||||
|
||||
return frag;
|
||||
}
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014 *
|
||||
* *
|
||||
* 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"
|
||||
#include <${MODULE_GLOBEBROWSING}/shaders/ellipsoid.hglsl>
|
||||
#include <${MODULE_GLOBEBROWSING}/shaders/texturetile.hglsl>
|
||||
|
||||
#define NUMLAYERS_COLORTEXTURE #{numLayersColor}
|
||||
#define NUMLAYERS_HEIGHTMAP #{numLayersHeight}
|
||||
|
||||
uniform mat4 modelViewProjectionTransform;
|
||||
uniform vec3 radiiSquared;
|
||||
|
||||
uniform vec2 minLatLon;
|
||||
uniform vec2 lonLatScalingFactor;
|
||||
|
||||
uniform TextureTile heightTiles[NUMLAYERS_HEIGHTMAP];
|
||||
|
||||
layout(location = 1) in vec2 in_uv;
|
||||
|
||||
out vec2 fs_uv;
|
||||
out vec4 fs_position;
|
||||
|
||||
PositionNormalPair globalInterpolation() {
|
||||
vec2 lonLatInput;
|
||||
lonLatInput.y = minLatLon.y + lonLatScalingFactor.y * in_uv.y; // Lat
|
||||
lonLatInput.x = minLatLon.x + lonLatScalingFactor.x * in_uv.x; // Lon
|
||||
PositionNormalPair positionPairModelSpace = geodetic2ToCartesian(lonLatInput.y, lonLatInput.x, radiiSquared);
|
||||
return positionPairModelSpace;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
PositionNormalPair pair = globalInterpolation();
|
||||
|
||||
float height = 0;
|
||||
for (int i = 0; i < NUMLAYERS_HEIGHTMAP; ++i)
|
||||
{
|
||||
vec2 samplePos =
|
||||
heightTiles[i].uvTransform.uvScale * in_uv +
|
||||
heightTiles[i].uvTransform.uvOffset;
|
||||
|
||||
float sampledValue = texture(heightTiles[i].textureSampler, samplePos).r;
|
||||
|
||||
// TODO : Some kind of blending here. Now it just writes over
|
||||
height = (sampledValue *
|
||||
heightTiles[i].depthTransform.depthScale +
|
||||
heightTiles[i].depthTransform.depthOffset);
|
||||
}
|
||||
|
||||
// Add the height in the direction of the normal
|
||||
pair.position += pair.normal * height;
|
||||
|
||||
vec4 position = modelViewProjectionTransform * vec4(pair.position, 1);
|
||||
|
||||
// Write output
|
||||
fs_uv = in_uv;
|
||||
fs_position = z_normalization(position);
|
||||
gl_Position = fs_position;
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014 *
|
||||
* *
|
||||
* 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. *
|
||||
****************************************************************************************/
|
||||
|
||||
uniform vec4 campos;
|
||||
uniform vec4 objpos;
|
||||
|
||||
uniform vec3 sun_pos;
|
||||
|
||||
uniform bool _performShading = true;
|
||||
uniform float transparency;
|
||||
uniform int shadows;
|
||||
|
||||
uniform float time;
|
||||
uniform sampler2D texture1;
|
||||
uniform sampler2D nightTex;
|
||||
|
||||
/*
|
||||
// Heightmap coverage
|
||||
uniform sampler2D textureSamplerHeight00;
|
||||
uniform sampler2D textureSamplerHeight10;
|
||||
uniform sampler2D textureSamplerHeight01;
|
||||
uniform sampler2D textureSamplerHeight11;
|
||||
uniform mat3 uvTransformPatchToTileHeight00;
|
||||
uniform mat3 uvTransformPatchToTileHeight10;
|
||||
uniform mat3 uvTransformPatchToTileHeight01;
|
||||
uniform mat3 uvTransformPatchToTileHeight11;
|
||||
*/
|
||||
|
||||
// Colortexture coverage
|
||||
uniform sampler2D textureSamplerColor00;
|
||||
uniform sampler2D textureSamplerColor10;
|
||||
uniform sampler2D textureSamplerColor01;
|
||||
uniform sampler2D textureSamplerColor11;
|
||||
uniform mat3 uvTransformPatchToTileColor00;
|
||||
uniform mat3 uvTransformPatchToTileColor10;
|
||||
uniform mat3 uvTransformPatchToTileColor01;
|
||||
uniform mat3 uvTransformPatchToTileColor11;
|
||||
|
||||
|
||||
//uniform int segmentsPerPatch;
|
||||
|
||||
in vec4 vs_position;
|
||||
in vec3 fs_position;
|
||||
in vec2 fs_uv;
|
||||
|
||||
|
||||
#include "PowerScaling/powerScaling_fs.hglsl"
|
||||
#include "fragment.glsl"
|
||||
|
||||
Fragment getFragment() {
|
||||
Fragment frag;
|
||||
|
||||
frag.color = vec4(0);
|
||||
vec4 color00, color10, color01, color11;
|
||||
|
||||
vec2 uv00 = vec2(uvTransformPatchToTileColor00 * vec3(fs_uv.s, fs_uv.t, 1));
|
||||
color00 = texture(textureSamplerColor00, uv00);
|
||||
|
||||
vec2 uv10 = vec2(uvTransformPatchToTileColor10 * vec3(fs_uv.s, fs_uv.t, 1));
|
||||
color10 += texture(textureSamplerColor10, uv10);
|
||||
|
||||
vec2 uv01 = vec2(uvTransformPatchToTileColor01 * vec3(fs_uv.s, fs_uv.t, 1));
|
||||
color01 += texture(textureSamplerColor01, uv01);
|
||||
|
||||
vec2 uv11 = vec2(uvTransformPatchToTileColor11 * vec3(fs_uv.s, fs_uv.t, 1));
|
||||
color11 += texture(textureSamplerColor11, uv11);
|
||||
|
||||
|
||||
frag.color = max(color00, max(color10, max(color01, color11))) * 10;
|
||||
|
||||
//vec4 uvColor = vec4(fract(fs_uv * segmentsPerPatch), 0.4,1);
|
||||
//frag.color = frag.color.a < 0.1 ? uvColor * 0.5 : frag.color;
|
||||
|
||||
frag.color = vec4(frag.color.r, frag.color.r, frag.color.r, 1);
|
||||
|
||||
frag.depth = vs_position.w;
|
||||
|
||||
return frag;
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014 *
|
||||
* *
|
||||
* 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__
|
||||
|
||||
uniform mat4 ViewProjection;
|
||||
uniform mat4 ModelTransform;
|
||||
|
||||
layout(location = 0) in vec4 in_position;
|
||||
|
||||
out vec4 vs_position;
|
||||
out vec2 vs_uv;
|
||||
|
||||
#include "PowerScaling/powerScaling_vs.hglsl"
|
||||
|
||||
void main()
|
||||
{
|
||||
// set variables
|
||||
vs_position = vec4(in_position.xyz * 60000000.0f, 1);
|
||||
vec4 tmp = vec4(in_position.xyz * 60000000.0f, 1);
|
||||
|
||||
vec4 position = pscTransform(tmp, ModelTransform);
|
||||
vs_position = tmp;
|
||||
vs_uv = vec2(0,0);
|
||||
position = ViewProjection * position;
|
||||
gl_Position = z_normalization(position);
|
||||
}
|
||||
@@ -40,7 +40,7 @@ namespace gui {
|
||||
void GuiTimeComponent::render() {
|
||||
float deltaTime = static_cast<float>(Time::ref().deltaTime());
|
||||
|
||||
bool changed = ImGui::SliderFloat("Delta Time", &deltaTime, -100.f, 100.f);
|
||||
bool changed = ImGui::SliderFloat("Delta Time", &deltaTime, -500000.f, 500000.f);
|
||||
if (changed)
|
||||
OsEng.scriptEngine().queueScript("openspace.time.setDeltaTime(" + std::to_string(deltaTime) + ")");
|
||||
|
||||
|
||||
@@ -885,6 +885,109 @@ void OrbitalInteractionMode::update(double deltaTime) {
|
||||
updateCameraStateFromMouseStates();
|
||||
}
|
||||
|
||||
GlobeBrowsingInteractionMode::GlobeBrowsingInteractionMode(
|
||||
std::shared_ptr<InputState> inputState,
|
||||
double sensitivity,
|
||||
double velocityScaleFactor)
|
||||
: OrbitalInteractionMode(inputState, sensitivity, velocityScaleFactor) {
|
||||
|
||||
}
|
||||
|
||||
GlobeBrowsingInteractionMode::~GlobeBrowsingInteractionMode() {
|
||||
|
||||
}
|
||||
|
||||
void GlobeBrowsingInteractionMode::setFocusNode(SceneGraphNode* focusNode) {
|
||||
_focusNode = focusNode;
|
||||
|
||||
Renderable* baseRenderable = _focusNode->renderable();
|
||||
if (RenderableGlobe* globe = dynamic_cast<RenderableGlobe*>(baseRenderable)) {
|
||||
_globe = globe;
|
||||
}
|
||||
else {
|
||||
_globe = nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GlobeBrowsingInteractionMode::updateCameraStateFromMouseStates() {
|
||||
if (_focusNode && _globe) {
|
||||
// Declare variables to use in interaction calculations
|
||||
glm::dvec3 centerPos = _focusNode->worldPosition().dvec3();
|
||||
glm::dvec3 camPos = _camera->positionVec3();
|
||||
glm::dvec3 posDiff = camPos - centerPos;
|
||||
glm::dvec3 newPosition = camPos;
|
||||
|
||||
glm::dvec3 centerToSurface = _globe->geodeticSurfaceProjection(camPos);
|
||||
glm::dvec3 surfaceToCamera = camPos - (centerPos + centerToSurface);
|
||||
glm::dvec3 directionFromSurfaceToCamera = glm::normalize(surfaceToCamera);
|
||||
double distFromCenterToSurface =
|
||||
glm::length(centerToSurface);
|
||||
double distFromSurfaceToCamera = glm::length(surfaceToCamera);
|
||||
double distFromCenterToCamera = glm::length(posDiff);
|
||||
|
||||
{ // Do local rotation
|
||||
glm::dvec3 eulerAngles(_localRotationMouseState.velocity.get().y, 0, 0);
|
||||
glm::dquat rotationDiff = glm::dquat(eulerAngles);
|
||||
|
||||
_localCameraRotation = _localCameraRotation * rotationDiff;
|
||||
}
|
||||
{ // Do global rotation
|
||||
glm::dvec3 eulerAngles(
|
||||
-_globalRotationMouseState.velocity.get().y,
|
||||
-_globalRotationMouseState.velocity.get().x,
|
||||
0);
|
||||
glm::dquat rotationDiffCamSpace = glm::dquat(eulerAngles);
|
||||
|
||||
|
||||
glm::dquat rotationDiffWorldSpace =
|
||||
_globalCameraRotation *
|
||||
rotationDiffCamSpace *
|
||||
glm::inverse(_globalCameraRotation);
|
||||
|
||||
glm::dvec3 rotationDiffVec3 =
|
||||
(distFromCenterToCamera * directionFromSurfaceToCamera)
|
||||
* rotationDiffWorldSpace
|
||||
- (distFromCenterToCamera * directionFromSurfaceToCamera);
|
||||
rotationDiffVec3 *= glm::clamp(distFromSurfaceToCamera / distFromCenterToSurface, 0.0, 1.0);
|
||||
|
||||
newPosition = camPos + rotationDiffVec3;
|
||||
|
||||
glm::dvec3 newCenterToSurface = _globe->geodeticSurfaceProjection(newPosition);
|
||||
glm::dvec3 newSurfaceToCamera = newPosition - (centerPos + newCenterToSurface);
|
||||
glm::dvec3 newDirectionFromSurfaceToCamera = glm::normalize(newSurfaceToCamera);
|
||||
|
||||
glm::dvec3 lookUpWhenFacingSurface =
|
||||
_globalCameraRotation * glm::dvec3(_camera->lookUpVectorCameraSpace());
|
||||
glm::dmat4 lookAtMat = glm::lookAt(
|
||||
glm::dvec3(0, 0, 0),
|
||||
-newDirectionFromSurfaceToCamera,
|
||||
lookUpWhenFacingSurface);
|
||||
_globalCameraRotation =
|
||||
glm::normalize(glm::quat_cast(glm::inverse(lookAtMat)));
|
||||
}
|
||||
{ // Move position towards or away from focus node
|
||||
newPosition += -(posDiff - centerToSurface) *
|
||||
_truckMovementMouseState.velocity.get().y;
|
||||
}
|
||||
{ // Do roll
|
||||
glm::dquat cameraRollRotation =
|
||||
glm::angleAxis(_rollMouseState.velocity.get().x, directionFromSurfaceToCamera);
|
||||
_globalCameraRotation = cameraRollRotation * _globalCameraRotation;
|
||||
}
|
||||
|
||||
// Update the camera state
|
||||
_camera->setRotation(_globalCameraRotation * _localCameraRotation);
|
||||
_camera->setPositionVec3(newPosition);
|
||||
}
|
||||
}
|
||||
|
||||
void GlobeBrowsingInteractionMode::update(double deltaTime) {
|
||||
updateMouseStatesFromInput(deltaTime);
|
||||
updateCameraStateFromMouseStates();
|
||||
}
|
||||
|
||||
// InteractionHandler
|
||||
InteractionHandler::InteractionHandler()
|
||||
: _origin("origin", "Origin", "")
|
||||
@@ -908,7 +1011,7 @@ InteractionHandler::InteractionHandler()
|
||||
|
||||
_inputState = std::shared_ptr<InputState>(new InputState());
|
||||
_interactor = std::shared_ptr<InteractionMode>(
|
||||
new OrbitalInteractionMode(_inputState, 0.002, 0.02));
|
||||
new GlobeBrowsingInteractionMode(_inputState, 0.002, 0.02));
|
||||
}
|
||||
|
||||
InteractionHandler::~InteractionHandler() {
|
||||
|
||||
@@ -43,8 +43,8 @@ namespace openspace {
|
||||
, _focusPosition()
|
||||
{
|
||||
_scaling.local = glm::vec2(1.f, 0.f);
|
||||
_position.local = Vec3(0, 0, 0);
|
||||
Vec3 eulerAngles(0, 0, 0);
|
||||
_position.local = Vec3(1.0, 1.0, 1.0);
|
||||
Vec3 eulerAngles(1.0, 1.0, 1.0);
|
||||
_rotation.local = Quat(eulerAngles);
|
||||
}
|
||||
|
||||
@@ -153,11 +153,12 @@ namespace openspace {
|
||||
|
||||
const Camera::Mat4& Camera::combinedViewMatrix() const {
|
||||
if (_cachedCombinedViewMatrix.isDirty) {
|
||||
glm::vec3 cameraPosition = position().vec3();
|
||||
glm::mat4 cameraTranslation =
|
||||
glm::inverse(glm::translate(glm::mat4(1.0), cameraPosition));
|
||||
Mat4 cameraTranslation =
|
||||
glm::inverse(glm::translate(Mat4(1.0), _position.shared));
|
||||
_cachedCombinedViewMatrix.datum =
|
||||
glm::mat4(viewRotationMatrix()) * cameraTranslation;
|
||||
Mat4(sgctInternal.viewMatrix()) *
|
||||
Mat4(viewRotationMatrix()) *
|
||||
cameraTranslation;
|
||||
}
|
||||
return _cachedCombinedViewMatrix.datum;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,45 @@ namespace openspace {
|
||||
|
||||
Time* Time::_instance = nullptr;
|
||||
|
||||
Time::Time()
|
||||
: _time(-1.0)
|
||||
, _dt(1.0)
|
||||
//local copies
|
||||
, _timeJumped(false)
|
||||
, _timePaused(false)
|
||||
, _jockeHasToFixThisLater(false)
|
||||
//shared copies
|
||||
, _sharedTime(-1.0)
|
||||
, _sharedDt(1.0)
|
||||
, _sharedTimeJumped(false)
|
||||
//synced copies
|
||||
, _syncedTime(-1.0)
|
||||
, _syncedDt(1.0)
|
||||
, _syncedTimeJumped(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
Time::Time(const Time& other)
|
||||
: _time(other._time)
|
||||
, _dt(other._dt)
|
||||
//local copies
|
||||
, _timeJumped(other._timeJumped)
|
||||
, _timePaused(other._timePaused)
|
||||
, _jockeHasToFixThisLater(other._jockeHasToFixThisLater)
|
||||
//shared copies
|
||||
, _sharedTime(other._sharedTime)
|
||||
, _sharedDt(other._sharedDt)
|
||||
, _sharedTimeJumped(other._sharedTimeJumped)
|
||||
//synced copies
|
||||
, _syncedTime(other._syncedTime)
|
||||
, _syncedDt(other._syncedDt)
|
||||
, _syncedTimeJumped(other._syncedTimeJumped)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Time::initialize() {
|
||||
ghoul_assert(_instance == nullptr, "Static time must not have been ininitialized");
|
||||
_instance = new Time();
|
||||
@@ -99,6 +138,29 @@ std::string Time::currentTimeUTC() const {
|
||||
return SpiceManager::ref().dateFromEphemerisTime(_syncedTime);
|
||||
}
|
||||
|
||||
std::string Time::ISO8601() const {
|
||||
std::string datetime = currentTimeUTC();
|
||||
std::string month = datetime.substr(5, 3);
|
||||
|
||||
std::string MM = "";
|
||||
if (month == "JAN") MM = "01";
|
||||
else if (month == "FEB") MM = "02";
|
||||
else if (month == "MAR") MM = "03";
|
||||
else if (month == "APR") MM = "04";
|
||||
else if (month == "MAY") MM = "05";
|
||||
else if (month == "JUN") MM = "06";
|
||||
else if (month == "JUL") MM = "07";
|
||||
else if (month == "AUG") MM = "08";
|
||||
else if (month == "SEP") MM = "09";
|
||||
else if (month == "OCT") MM = "10";
|
||||
else if (month == "NOV") MM = "11";
|
||||
else if (month == "DEC") MM = "12";
|
||||
else ghoul_assert(false, "Bad month");
|
||||
|
||||
datetime.replace(4, 5, "-" + MM + "-");
|
||||
return datetime;
|
||||
}
|
||||
|
||||
void Time::serialize(SyncBuffer* syncBuffer) {
|
||||
_syncMutex.lock();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user