From d414003424ab1e20d25becbebc7eeecb24b6082d Mon Sep 17 00:00:00 2001 From: Erik Broberg Date: Mon, 4 Apr 2016 15:16:47 -0400 Subject: [PATCH 1/4] added files for Quadtree class and unit test file --- modules/globebrowsing/CMakeLists.txt | 3 ++ .../globebrowsing/datastructures/quadtree.cpp | 34 ++++++++++++++++ .../globebrowsing/datastructures/quadtree.h | 40 +++++++++++++++++++ tests/main.cpp | 19 ++++++--- tests/test_quadtree.inl | 40 +++++++++++++++++++ 5 files changed, 130 insertions(+), 6 deletions(-) create mode 100644 modules/globebrowsing/datastructures/quadtree.cpp create mode 100644 modules/globebrowsing/datastructures/quadtree.h create mode 100644 tests/test_quadtree.inl diff --git a/modules/globebrowsing/CMakeLists.txt b/modules/globebrowsing/CMakeLists.txt index a7b3a9d59d..692ed65599 100644 --- a/modules/globebrowsing/CMakeLists.txt +++ b/modules/globebrowsing/CMakeLists.txt @@ -30,6 +30,8 @@ set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rendering/geometry.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/gridgeometry.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/globemesh.h + + ${CMAKE_CURRENT_SOURCE_DIR}/datastructures/quadtree.h ) source_group("Header Files" FILES ${HEADER_FILES}) @@ -40,6 +42,7 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rendering/gridgeometry.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/globemesh.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/datastructures/quadtree.cpp ) source_group("Source Files" FILES ${SOURCE_FILES}) diff --git a/modules/globebrowsing/datastructures/quadtree.cpp b/modules/globebrowsing/datastructures/quadtree.cpp new file mode 100644 index 0000000000..c93951c40d --- /dev/null +++ b/modules/globebrowsing/datastructures/quadtree.cpp @@ -0,0 +1,34 @@ +/***************************************************************************************** + * * + * 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 + +namespace openspace { + +Quadtree::Quadtree() { + +} + + +} // namespace openspace \ No newline at end of file diff --git a/modules/globebrowsing/datastructures/quadtree.h b/modules/globebrowsing/datastructures/quadtree.h new file mode 100644 index 0000000000..0b23c92f68 --- /dev/null +++ b/modules/globebrowsing/datastructures/quadtree.h @@ -0,0 +1,40 @@ +/***************************************************************************************** + * * + * 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 __QUADTREE_H__ +#define __QUADTREE_H__ + + +namespace openspace { + +class Quadtree { +public: + Quadtree(); + + +}; + +} // namespace openspace + +#endif // __QUADTREE_H__ diff --git a/tests/main.cpp b/tests/main.cpp index 6f39f9b1af..1a53c80947 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -32,7 +32,8 @@ #include //#include -#include +//#include +#include //#include //#include #include @@ -48,13 +49,19 @@ using namespace ghoul::filesystem; using namespace ghoul::logging; namespace { - std::string _loggerCat = "OpenSpaceTest"; + std::string _loggerCat = "OpenSpaceTest"; } int main(int argc, char** argv) { - std::vector args; - openspace::OpenSpaceEngine::create(argc, argv, std::make_unique(), args); + std::vector args; + openspace::OpenSpaceEngine::create(argc, argv, std::make_unique(), args); - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); + testing::InitGoogleTest(&argc, argv); + + int returnVal = RUN_ALL_TESTS(); + + // keep console from closing down + int dummy; std::cin >> dummy; + + return returnVal; } diff --git a/tests/test_quadtree.inl b/tests/test_quadtree.inl new file mode 100644 index 0000000000..df8960b6d4 --- /dev/null +++ b/tests/test_quadtree.inl @@ -0,0 +1,40 @@ +/***************************************************************************************** + * * + * 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 "gtest/gtest.h" + +#include +#include + +#include + +class QuadtreeTest : public testing::Test {}; + +using namespace openspace; + +TEST_F(QuadtreeTest, ConstructorTest) { + Quadtree t; + EXPECT_TRUE(&t != nullptr) << "Quadtree was constructed"; +} + From b0ab03bb37641934b2381b9a1eaa6ea05b1a92d8 Mon Sep 17 00:00:00 2001 From: Erik Broberg Date: Tue, 5 Apr 2016 19:14:50 -0400 Subject: [PATCH 2/4] Added ChunkNode class --- modules/globebrowsing/CMakeLists.txt | 22 +++--- .../{quadtree.h => chunknode.h} | 61 ++++++++++++++-- .../{quadtree.cpp => chunknode.inl} | 71 ++++++++++++++++++- tests/main.cpp | 2 +- .../{test_quadtree.inl => test_chunknode.inl} | 40 +++++++++-- 5 files changed, 171 insertions(+), 25 deletions(-) rename modules/globebrowsing/datastructures/{quadtree.h => chunknode.h} (74%) rename modules/globebrowsing/datastructures/{quadtree.cpp => chunknode.inl} (53%) rename tests/{test_quadtree.inl => test_chunknode.inl} (62%) diff --git a/modules/globebrowsing/CMakeLists.txt b/modules/globebrowsing/CMakeLists.txt index 692ed65599..67e7f01350 100644 --- a/modules/globebrowsing/CMakeLists.txt +++ b/modules/globebrowsing/CMakeLists.txt @@ -25,13 +25,15 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) set(HEADER_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableglobe.h - ${CMAKE_CURRENT_SOURCE_DIR}/rendering/distanceswitch.h - ${CMAKE_CURRENT_SOURCE_DIR}/rendering/geometry.h - ${CMAKE_CURRENT_SOURCE_DIR}/rendering/gridgeometry.h - ${CMAKE_CURRENT_SOURCE_DIR}/rendering/globemesh.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableglobe.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/distanceswitch.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/geometry.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/gridgeometry.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/globemesh.h + + ${CMAKE_CURRENT_SOURCE_DIR}/datastructures/chunknode.h + ${CMAKE_CURRENT_SOURCE_DIR}/datastructures/chunknode.inl - ${CMAKE_CURRENT_SOURCE_DIR}/datastructures/quadtree.h ) source_group("Header Files" FILES ${HEADER_FILES}) @@ -42,7 +44,7 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rendering/gridgeometry.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/globemesh.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/datastructures/quadtree.cpp + ) source_group("Source Files" FILES ${SOURCE_FILES}) @@ -52,7 +54,7 @@ set(SHADER_FILES source_group("Shader Files" FILES ${SHADER_FILES}) create_new_module( - "GlobeBrowsing" - globebrowsing_module - ${HEADER_FILES} ${SOURCE_FILES} ${SHADER_FILES} + "GlobeBrowsing" + globebrowsing_module + ${HEADER_FILES} ${SOURCE_FILES} ${SHADER_FILES} ) diff --git a/modules/globebrowsing/datastructures/quadtree.h b/modules/globebrowsing/datastructures/chunknode.h similarity index 74% rename from modules/globebrowsing/datastructures/quadtree.h rename to modules/globebrowsing/datastructures/chunknode.h index 0b23c92f68..4563d4e16c 100644 --- a/modules/globebrowsing/datastructures/quadtree.h +++ b/modules/globebrowsing/datastructures/chunknode.h @@ -25,16 +25,67 @@ #ifndef __QUADTREE_H__ #define __QUADTREE_H__ +#include +#include +#include +#include + +// Using double precision +typedef double Scalar; +typedef glm::dvec2 Vec2; namespace openspace { -class Quadtree { -public: - Quadtree(); - - +enum Quad { + NORTH_WEST, + NORTH_EAST, + SOUTH_WEST, + SOUTH_EAST }; + + +struct BoundingRect { + BoundingRect(Scalar, Scalar, Scalar, Scalar); + BoundingRect(const Vec2& center, const Vec2& halfSize); + Vec2 center; + Vec2 halfSize; +}; + + + + + +class ChunkNode { +public: + ChunkNode(const BoundingRect&, ChunkNode* parent = nullptr); + ~ChunkNode(); + + + void split(); + void merge(); + + bool isRoot() const; + bool isLeaf() const; + + + const ChunkNode& getChild(Quad quad) const; + const BoundingRect bounds; + +private: + + + ChunkNode* _parent; + std::unique_ptr _children[4]; + +}; + + + } // namespace openspace + +#include + + #endif // __QUADTREE_H__ diff --git a/modules/globebrowsing/datastructures/quadtree.cpp b/modules/globebrowsing/datastructures/chunknode.inl similarity index 53% rename from modules/globebrowsing/datastructures/quadtree.cpp rename to modules/globebrowsing/datastructures/chunknode.inl index c93951c40d..fe1e5abce3 100644 --- a/modules/globebrowsing/datastructures/quadtree.cpp +++ b/modules/globebrowsing/datastructures/chunknode.inl @@ -22,13 +22,78 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#include +#include + namespace openspace { -Quadtree::Quadtree() { +BoundingRect::BoundingRect(Scalar cx, Scalar cy, Scalar hsx, Scalar hsy) + : center(Vec2(cx, cy)), halfSize(Vec2(hsx, hsy)) { } +BoundingRect::BoundingRect(const Vec2& center, const Vec2& halfSize) + :center(center), halfSize(halfSize) { } + + + + +ChunkNode::ChunkNode(const BoundingRect& bounds, ChunkNode* parent) +: bounds(bounds), _parent(parent) +{ + _children[0] = nullptr; + _children[1] = nullptr; + _children[2] = nullptr; + _children[3] = nullptr; +} + +ChunkNode::~ChunkNode() { + +} + +bool ChunkNode::isRoot() const { + return _parent == nullptr; +} + +bool ChunkNode::isLeaf() const { + return _children[0] == nullptr; } -} // namespace openspace \ No newline at end of file +void ChunkNode::split() { + // Defining short handles for center, halfSize and quarterSize + const Vec2& c = bounds.center; + const Vec2& hs =bounds.halfSize; + Vec2 qs = 0.5 * bounds.halfSize; + + // Subdivide bounds + BoundingRect nwBounds = BoundingRect(c + Vec2(-qs.x, -qs.y), qs); + BoundingRect neBounds = BoundingRect(c + Vec2(+qs.x, -qs.y), qs); + BoundingRect swBounds = BoundingRect(c + Vec2(-qs.x, +qs.y), qs); + BoundingRect seBounds = BoundingRect(c + Vec2(+qs.x, +qs.y), qs); + + // Create new chunk nodes + _children[Quad::NORTH_WEST] = std::unique_ptr(new ChunkNode(nwBounds, this)); + _children[Quad::NORTH_EAST] = std::unique_ptr(new ChunkNode(neBounds, this)); + _children[Quad::SOUTH_WEST] = std::unique_ptr(new ChunkNode(swBounds, this)); + _children[Quad::SOUTH_EAST] = std::unique_ptr(new ChunkNode(seBounds, this)); +} + + +void ChunkNode::merge() { + for (int i = 0; i < 4; ++i) { + if (_children[i] != nullptr) { + _children[i]->merge(); + } + _children[i] = nullptr; + } +} + + +const ChunkNode& ChunkNode::getChild(Quad quad) const { + return *_children[quad]; +} + + + + + +} // namespace openspace diff --git a/tests/main.cpp b/tests/main.cpp index 1a53c80947..cd9815caee 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -33,7 +33,7 @@ #include //#include //#include -#include +#include //#include //#include #include diff --git a/tests/test_quadtree.inl b/tests/test_chunknode.inl similarity index 62% rename from tests/test_quadtree.inl rename to tests/test_chunknode.inl index df8960b6d4..e5e87ef7f7 100644 --- a/tests/test_quadtree.inl +++ b/tests/test_chunknode.inl @@ -25,16 +25,44 @@ #include "gtest/gtest.h" #include -#include +#include #include - -class QuadtreeTest : public testing::Test {}; +#include using namespace openspace; -TEST_F(QuadtreeTest, ConstructorTest) { - Quadtree t; - EXPECT_TRUE(&t != nullptr) << "Quadtree was constructed"; +class ChunkNodeTest : public testing::Test {}; + +TEST_F(ChunkNodeTest, Split) { + BoundingRect bounds(Vec2(2, 2), Vec2(2, 2)); + auto cn = std::shared_ptr(new ChunkNode(bounds)); + ASSERT_TRUE(cn->isRoot()) << "Chunk node is root"; + ASSERT_TRUE(cn->isLeaf()) << "Chunk node is leaf"; + + cn->split(); + ASSERT_TRUE(cn->isRoot()) << "Chunk node is root"; + ASSERT_FALSE(cn->isLeaf()) << "Chunk node is not leaf"; + + ASSERT_EQ(cn->bounds.center.x, cn->getChild(Quad::NORTH_WEST).bounds.center.x * 2); + ASSERT_EQ(cn->bounds.center.x, cn->getChild(Quad::NORTH_EAST).bounds.center.x * 2/3); + + ASSERT_EQ(cn->bounds.halfSize.x, cn->getChild(Quad::NORTH_WEST).bounds.halfSize.x * 2); + ASSERT_EQ(cn->bounds.halfSize.y, cn->getChild(Quad::NORTH_WEST).bounds.halfSize.y * 2); } +TEST_F(ChunkNodeTest, Merge) { + BoundingRect bounds(Vec2(2, 2), Vec2(2, 2)); + ChunkNode cn(bounds); + ASSERT_TRUE(cn.isRoot()) << "Chunk node is root"; + ASSERT_TRUE(cn.isLeaf()) << "Chunk node is leaf"; + + cn.split(); + ASSERT_TRUE(cn.isRoot()) << "Chunk node is root"; + ASSERT_FALSE(cn.isLeaf()) << "Chunk node is not leaf"; + + cn.merge(); + ASSERT_TRUE(cn.isRoot()) << "Chunk node is root"; + ASSERT_TRUE(cn.isLeaf()) << "Chunk node is leaf"; + +} \ No newline at end of file From 25a917bf1a369b0c09b00df674cc5a115f88e15b Mon Sep 17 00:00:00 2001 From: Erik Broberg Date: Wed, 6 Apr 2016 17:08:20 -0400 Subject: [PATCH 3/4] placed camera att nice distance --- data/scene/globebrowsing.scene | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/scene/globebrowsing.scene b/data/scene/globebrowsing.scene index 594cd7c5ed..e1326b09a2 100644 --- a/data/scene/globebrowsing.scene +++ b/data/scene/globebrowsing.scene @@ -3,7 +3,7 @@ return { CommonFolder = "common", Camera = { Focus = "DebugGlobe", - Position = {1, 0, 0, 5}, + Position = {1, 0, 0, 7}, }, Modules = { "debugglobe", From efe2bef2d4489ced985feb1bfc6faea1adf17757 Mon Sep 17 00:00:00 2001 From: Erik Broberg Date: Wed, 6 Apr 2016 17:10:29 -0400 Subject: [PATCH 4/4] Created Chunk LOD Globe. Currently renders patches at constant depth --- modules/globebrowsing/CMakeLists.txt | 8 +- .../{chunknode.inl => chunknode.cpp} | 105 +++++++++++--- .../globebrowsing/datastructures/chunknode.h | 37 +++-- modules/globebrowsing/globebrowsingmodule.cpp | 2 +- .../globebrowsing/rendering/chunklodglobe.cpp | 131 ++++++++++++++++++ .../globebrowsing/rendering/chunklodglobe.h | 92 ++++++++++++ .../globebrowsing/rendering/clipmapglobe.h | 3 + .../globebrowsing/rendering/gridgeometry.cpp | 4 +- .../globebrowsing/rendering/latlonpatch.cpp | 16 ++- modules/globebrowsing/rendering/latlonpatch.h | 1 + .../rendering/renderableglobe.cpp | 4 +- .../shaders/latlonpatch_spheremapping_vs.glsl | 3 + modules/globebrowsing/shaders/simple_fs.glsl | 4 +- 13 files changed, 373 insertions(+), 37 deletions(-) rename modules/globebrowsing/datastructures/{chunknode.inl => chunknode.cpp} (55%) create mode 100644 modules/globebrowsing/rendering/chunklodglobe.cpp create mode 100644 modules/globebrowsing/rendering/chunklodglobe.h diff --git a/modules/globebrowsing/CMakeLists.txt b/modules/globebrowsing/CMakeLists.txt index bf02729c03..dd831bbbec 100644 --- a/modules/globebrowsing/CMakeLists.txt +++ b/modules/globebrowsing/CMakeLists.txt @@ -36,10 +36,11 @@ set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rendering/latlonpatch.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/clipmapglobe.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/chunklodglobe.h - ${CMAKE_CURRENT_SOURCE_DIR}/util/converter.h ${CMAKE_CURRENT_SOURCE_DIR}/datastructures/chunknode.h - ${CMAKE_CURRENT_SOURCE_DIR}/datastructures/chunknode.inl + + ${CMAKE_CURRENT_SOURCE_DIR}/util/converter.h + ) set(SOURCE_FILES @@ -51,6 +52,9 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rendering/latlonpatch.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/clipmapglobe.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/chunklodglobe.cpp + + ${CMAKE_CURRENT_SOURCE_DIR}/datastructures/chunknode.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/util/converter.cpp diff --git a/modules/globebrowsing/datastructures/chunknode.inl b/modules/globebrowsing/datastructures/chunknode.cpp similarity index 55% rename from modules/globebrowsing/datastructures/chunknode.inl rename to modules/globebrowsing/datastructures/chunknode.cpp index fe1e5abce3..a6094bbb4e 100644 --- a/modules/globebrowsing/datastructures/chunknode.inl +++ b/modules/globebrowsing/datastructures/chunknode.cpp @@ -23,7 +23,7 @@ ****************************************************************************************/ #include - +#include namespace openspace { @@ -36,8 +36,12 @@ BoundingRect::BoundingRect(const Vec2& center, const Vec2& halfSize) -ChunkNode::ChunkNode(const BoundingRect& bounds, ChunkNode* parent) -: bounds(bounds), _parent(parent) + + +ChunkNode::ChunkNode(ChunkLodGlobe& owner, const BoundingRect& bounds, ChunkNode* parent) +: _owner(owner) +, bounds(bounds) +, _parent(parent) { _children[0] = nullptr; _children[1] = nullptr; @@ -58,23 +62,88 @@ bool ChunkNode::isLeaf() const { } -void ChunkNode::split() { - // Defining short handles for center, halfSize and quarterSize - const Vec2& c = bounds.center; - const Vec2& hs =bounds.halfSize; - Vec2 qs = 0.5 * bounds.halfSize; - // Subdivide bounds - BoundingRect nwBounds = BoundingRect(c + Vec2(-qs.x, -qs.y), qs); - BoundingRect neBounds = BoundingRect(c + Vec2(+qs.x, -qs.y), qs); - BoundingRect swBounds = BoundingRect(c + Vec2(-qs.x, +qs.y), qs); - BoundingRect seBounds = BoundingRect(c + Vec2(+qs.x, +qs.y), qs); +bool ChunkNode::initialize() { + if (!isLeaf()) { + for (int i = 0; i < 4; ++i) { + _children[i]->initialize(); + } + } + + return isReady(); +} - // Create new chunk nodes - _children[Quad::NORTH_WEST] = std::unique_ptr(new ChunkNode(nwBounds, this)); - _children[Quad::NORTH_EAST] = std::unique_ptr(new ChunkNode(neBounds, this)); - _children[Quad::SOUTH_WEST] = std::unique_ptr(new ChunkNode(swBounds, this)); - _children[Quad::SOUTH_EAST] = std::unique_ptr(new ChunkNode(seBounds, this)); +bool ChunkNode::deinitialize() { + if (!isLeaf()) { + for (int i = 0; i < 4; ++i) { + _children[i]->deinitialize(); + } + } + return true; +} + +bool ChunkNode::isReady() const{ + bool ready = true; + return ready; +} + +void ChunkNode::render(const RenderData& data) { + internalRender(data, 0); +} + +void ChunkNode::internalRender(const RenderData& data, int currLevel) { + if (isLeaf()) { + LatLonPatch& templatePatch = _owner.getTemplatePatch(); + templatePatch.setPositionLatLon(bounds.center); + templatePatch.setSizeLatLon(bounds.halfSize); + templatePatch.render(data); + } + else { + for (int i = 0; i < 4; ++i) { + _children[i]->internalRender(data, currLevel+1); + } + } +} + +void ChunkNode::update(const UpdateData& data) { + internalUpdate(data, 0); +} + +void ChunkNode::internalUpdate(const UpdateData& data, int currLevel) { + if (!isLeaf()) { + for (int i = 0; i < 4; ++i) { + _children[i]->internalUpdate(data, currLevel + 1); + } + } +} + + +void ChunkNode::split(int depth) { + if (depth > 0 && isLeaf()) { + + // Defining short handles for center, halfSize and quarterSize + const Vec2& c = bounds.center; + const Vec2& hs = bounds.halfSize; + Vec2 qs = 0.5 * bounds.halfSize; + + // Subdivide bounds + BoundingRect nwBounds = BoundingRect(c + Vec2(-qs.x, -qs.y), qs); + BoundingRect neBounds = BoundingRect(c + Vec2(+qs.x, -qs.y), qs); + BoundingRect swBounds = BoundingRect(c + Vec2(-qs.x, +qs.y), qs); + BoundingRect seBounds = BoundingRect(c + Vec2(+qs.x, +qs.y), qs); + + // Create new chunk nodes + _children[Quad::NORTH_WEST] = std::unique_ptr(new ChunkNode(_owner, nwBounds, this)); + _children[Quad::NORTH_EAST] = std::unique_ptr(new ChunkNode(_owner, neBounds, this)); + _children[Quad::SOUTH_WEST] = std::unique_ptr(new ChunkNode(_owner, swBounds, this)); + _children[Quad::SOUTH_EAST] = std::unique_ptr(new ChunkNode(_owner, seBounds, this)); + } + + if (depth - 1 > 0) { + for (int i = 0; i < 4; ++i) { + _children[i]->split(depth - 1); + } + } } diff --git a/modules/globebrowsing/datastructures/chunknode.h b/modules/globebrowsing/datastructures/chunknode.h index 4563d4e16c..b74bb4f540 100644 --- a/modules/globebrowsing/datastructures/chunknode.h +++ b/modules/globebrowsing/datastructures/chunknode.h @@ -30,6 +30,16 @@ #include #include +#include + + +// forward declaration +namespace openspace { + class ChunkLodGlobe; +} + + + // Using double precision typedef double Scalar; typedef glm::dvec2 Vec2; @@ -56,28 +66,41 @@ struct BoundingRect { -class ChunkNode { +class ChunkNode : public Renderable{ public: - ChunkNode(const BoundingRect&, ChunkNode* parent = nullptr); + ChunkNode(ChunkLodGlobe&, const BoundingRect&, ChunkNode* parent = nullptr); ~ChunkNode(); - void split(); + void split(int depth = 1); void merge(); - + bool isRoot() const; bool isLeaf() const; - const ChunkNode& getChild(Quad quad) const; const BoundingRect bounds; + + + bool initialize() override; + bool deinitialize() override; + bool isReady() const override; + + void render(const RenderData& data) override; + void update(const UpdateData& data) override; + + void internalRender(const RenderData& data, int currLevel); + void internalUpdate(const UpdateData& data, int currLevel); + private: - + ChunkNode* _parent; std::unique_ptr _children[4]; + ChunkLodGlobe& _owner; + }; @@ -85,7 +108,5 @@ private: } // namespace openspace -#include - #endif // __QUADTREE_H__ diff --git a/modules/globebrowsing/globebrowsingmodule.cpp b/modules/globebrowsing/globebrowsingmodule.cpp index ce39039fea..78cbdee253 100644 --- a/modules/globebrowsing/globebrowsingmodule.cpp +++ b/modules/globebrowsing/globebrowsingmodule.cpp @@ -37,7 +37,7 @@ namespace openspace { GlobeBrowsingModule::GlobeBrowsingModule() - : OpenSpaceModule("GlobeBrowsing") + : OpenSpaceModule("GlobeBrowsing") {} void GlobeBrowsingModule::internalInitialize() { diff --git a/modules/globebrowsing/rendering/chunklodglobe.cpp b/modules/globebrowsing/rendering/chunklodglobe.cpp new file mode 100644 index 0000000000..d59c04bbfa --- /dev/null +++ b/modules/globebrowsing/rendering/chunklodglobe.cpp @@ -0,0 +1,131 @@ +/***************************************************************************************** +* * +* 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 + +#include + +// open space includes +#include +#include +#include +#include + +// ghoul includes +#include + +#define _USE_MATH_DEFINES +#include + +namespace { + const std::string _loggerCat = "ChunkLodGlobe"; + + const std::string keyFrame = "Frame"; + const std::string keyGeometry = "Geometry"; + const std::string keyShading = "PerformShading"; + + const std::string keyBody = "Body"; +} + +namespace openspace { + + const BoundingRect ChunkLodGlobe::LEFT_HEMISPHERE = BoundingRect(0, -M_PI/2, M_PI/2, M_PI/2); + const BoundingRect ChunkLodGlobe::RIGHT_HEMISPHERE = BoundingRect(0, M_PI/2, M_PI/2, M_PI/2); + + + ChunkLodGlobe::ChunkLodGlobe(const ghoul::Dictionary& dictionary) + : _leftRoot(new ChunkNode(*this, LEFT_HEMISPHERE)) + , _rightRoot(new ChunkNode(*this, RIGHT_HEMISPHERE)) + , _templatePatch(10,10, 0, 0, 0, 0) + , _rotation("rotation", "Rotation", 0, 0, 360) + { + std::string name; + bool success = dictionary.getValue(SceneGraphNode::KeyName, name); + ghoul_assert(success, + "ChunkLodGlobe need the '" << SceneGraphNode::KeyName << "' be specified"); + setName(name); + + dictionary.getValue(keyFrame, _frame); + dictionary.getValue(keyBody, _target); + if (_target != "") + setBody(_target); + + // Mainly for debugging purposes @AA + addProperty(_rotation); + + + // ----- specific for this class only ------ // + _leftRoot->split(5); + _rightRoot->split(5); + } + + ChunkLodGlobe::~ChunkLodGlobe() { + + } + + LatLonPatch& ChunkLodGlobe::getTemplatePatch() { + return _templatePatch; + } + + bool ChunkLodGlobe::initialize() { + _templatePatch.initialize(); + _leftRoot->initialize(); + _rightRoot->initialize(); + return isReady(); + } + + bool ChunkLodGlobe::deinitialize() { + _templatePatch.deinitialize(); + _leftRoot->deinitialize(); + _rightRoot->deinitialize(); + return true; + } + + bool ChunkLodGlobe::isReady() const { + bool ready = true; + ready &= _templatePatch.isReady(); + ready &= _leftRoot->isReady(); + ready &= _rightRoot->isReady(); + return ready; + } + + void ChunkLodGlobe::render(const RenderData& data) + { + // Set patch to follow camera + //_patch.setPositionLatLon(converter::cartesianToLatLon(data.camera.position().dvec3())); + // render + _leftRoot->render(data); + _rightRoot->render(data); + } + + void ChunkLodGlobe::update(const UpdateData& data) { + _templatePatch.update(data); + // set spice-orientation in accordance to timestamp + _stateMatrix = SpiceManager::ref().positionTransformMatrix(_frame, "GALACTIC", data.time); + _time = data.time; + } + + + +} // namespace openspace diff --git a/modules/globebrowsing/rendering/chunklodglobe.h b/modules/globebrowsing/rendering/chunklodglobe.h new file mode 100644 index 0000000000..a7f9182aaa --- /dev/null +++ b/modules/globebrowsing/rendering/chunklodglobe.h @@ -0,0 +1,92 @@ +/***************************************************************************************** +* * +* 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 __CHUNK_LOD_GLOBE__ +#define __CHUNK_LOD_GLOBE__ + +#include + +// open space includes +#include + +#include +#include + +#include + +#include +#include +#include +#include + +namespace ghoul { + namespace opengl { + class ProgramObject; + } +} + +namespace openspace { + + class ChunkLodGlobe : + public Renderable, public std::enable_shared_from_this{ + public: + ChunkLodGlobe(const ghoul::Dictionary& dictionary); + ~ChunkLodGlobe(); + + LatLonPatch& getTemplatePatch(); + + bool initialize() override; + bool deinitialize() override; + bool isReady() const override; + + void render(const RenderData& data) override; + void update(const UpdateData& data) override; + + + + private: + + // Covers all negative longitudes + std::unique_ptr _leftRoot; + + // Covers all positive longitudes + std::unique_ptr _rightRoot; + + // the patch used for actual rendering + LatLonPatch _templatePatch; + + static const BoundingRect LEFT_HEMISPHERE; + static const BoundingRect RIGHT_HEMISPHERE; + + properties::IntProperty _rotation; + + glm::dmat3 _stateMatrix; + std::string _frame; + std::string _target; + double _time; + }; + +} // namespace openspace + +#endif // __CHUNK_LOD_GLOBE__ \ No newline at end of file diff --git a/modules/globebrowsing/rendering/clipmapglobe.h b/modules/globebrowsing/rendering/clipmapglobe.h index 6a5296f9ab..83d3b98bec 100644 --- a/modules/globebrowsing/rendering/clipmapglobe.h +++ b/modules/globebrowsing/rendering/clipmapglobe.h @@ -31,11 +31,14 @@ #include #include + #include #include #include #include + + namespace ghoul { namespace opengl { class ProgramObject; diff --git a/modules/globebrowsing/rendering/gridgeometry.cpp b/modules/globebrowsing/rendering/gridgeometry.cpp index c6cceab266..c698399064 100644 --- a/modules/globebrowsing/rendering/gridgeometry.cpp +++ b/modules/globebrowsing/rendering/gridgeometry.cpp @@ -86,13 +86,13 @@ std::vector GridGeometry::CreateElements(unsigned int xRes, unsigned int // add upper triangle elements.push_back(v00); - elements.push_back(v10); elements.push_back(v01); + elements.push_back(v10); // add lower triangle elements.push_back(v01); - elements.push_back(v10); elements.push_back(v11); + elements.push_back(v10); //LDEBUG(v00 << ", " << v10 << ", " << v01); //LDEBUG(v01 << ", " << v10 << ", " << v11); diff --git a/modules/globebrowsing/rendering/latlonpatch.cpp b/modules/globebrowsing/rendering/latlonpatch.cpp index 3fea6a51d2..ef549248b5 100644 --- a/modules/globebrowsing/rendering/latlonpatch.cpp +++ b/modules/globebrowsing/rendering/latlonpatch.cpp @@ -110,7 +110,7 @@ namespace openspace { // TODO : Not sure if double precision will be needed for all these calculations // Using doubles in case but might slow things down. // TODO : Need to get the radius of the globe - double r = 6e6; + double r = 6.3e6; // Create control points (double) glm::dvec3 p00, p01, p10, p11; @@ -148,10 +148,13 @@ namespace openspace { glm::dvec3 camPos = data.camera.position().dvec3(); glm::dvec3 camDir = glm::normalize(position - camPos); glm::dvec3 camUp = glm::dvec3(0,1,0);// data.camera.lookUpVector(); + // Get camera transform matrix (double precision) glm::dmat4 viewTransform = glm::inverse(glm::translate(glm::dmat4(1.0), camPos)); + //glm::dmat4 viewTransform = glm::lookAt(camPos, camPos + camDir, camUp); - viewTransform = glm::dmat4( data.camera.viewRotationMatrix()) * viewTransform; + viewTransform = glm::dmat4(data.camera.viewRotationMatrix())*viewTransform; + // Transform control points to camera space p00 = glm::dvec3(viewTransform * glm::dvec4(p00, 1.0)); p10 = glm::dvec3(viewTransform * glm::dvec4(p10, 1.0)); @@ -169,8 +172,8 @@ namespace openspace { _programObject->setUniform("Projection", data.camera.projectionMatrix()); // Render triangles (use texture coordinates to interpolate to new positions) - glDisable(GL_CULL_FACE); - //glCullFace(GL_BACK); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); // render _grid.drawUsingActiveProgram(); @@ -187,4 +190,9 @@ namespace openspace { _posLatLon = posLatLon; } + void LatLonPatch::setSizeLatLon(glm::dvec2 sizeLatLon) { + _sizeLatLon = sizeLatLon; + } + + } // namespace openspace diff --git a/modules/globebrowsing/rendering/latlonpatch.h b/modules/globebrowsing/rendering/latlonpatch.h index 5267f8f0eb..6e101e1485 100644 --- a/modules/globebrowsing/rendering/latlonpatch.h +++ b/modules/globebrowsing/rendering/latlonpatch.h @@ -60,6 +60,7 @@ namespace openspace { void update(const UpdateData& data) override; void setPositionLatLon(glm::dvec2 posLatLon); + void setSizeLatLon(glm::dvec2 posLatLon); private: std::unique_ptr _programObject; diff --git a/modules/globebrowsing/rendering/renderableglobe.cpp b/modules/globebrowsing/rendering/renderableglobe.cpp index b2270c3124..c8df9a1707 100644 --- a/modules/globebrowsing/rendering/renderableglobe.cpp +++ b/modules/globebrowsing/rendering/renderableglobe.cpp @@ -26,6 +26,7 @@ #include #include +#include // open space includes #include @@ -69,7 +70,8 @@ namespace openspace { // Mainly for debugging purposes @AA addProperty(_rotation); - addSwitchValue(std::shared_ptr(new ClipMapGlobe(dictionary)), 1e9); + //addSwitchValue(std::shared_ptr(new ClipMapGlobe(dictionary)), 1e9); + addSwitchValue(std::shared_ptr(new ChunkLodGlobe(dictionary)), 1e9); addSwitchValue(std::shared_ptr(new GlobeMesh(dictionary)), 1e10); } diff --git a/modules/globebrowsing/shaders/latlonpatch_spheremapping_vs.glsl b/modules/globebrowsing/shaders/latlonpatch_spheremapping_vs.glsl index 541470d16b..e0953e029c 100644 --- a/modules/globebrowsing/shaders/latlonpatch_spheremapping_vs.glsl +++ b/modules/globebrowsing/shaders/latlonpatch_spheremapping_vs.glsl @@ -34,11 +34,14 @@ uniform vec3 p11; layout(location = 1) in vec2 in_UV; out vec4 vs_position; +out vec2 vs_uv; #include "PowerScaling/powerScaling_vs.hglsl" void main() { + vs_uv = in_UV; + // Bilinear interpolation vec3 p0 = (1 - in_UV.x) * p00 + in_UV.x * p10; vec3 p1 = (1 - in_UV.x) * p01 + in_UV.x * p11; diff --git a/modules/globebrowsing/shaders/simple_fs.glsl b/modules/globebrowsing/shaders/simple_fs.glsl index 9610505039..7e25915740 100644 --- a/modules/globebrowsing/shaders/simple_fs.glsl +++ b/modules/globebrowsing/shaders/simple_fs.glsl @@ -36,6 +36,8 @@ uniform sampler2D texture1; uniform sampler2D nightTex; in vec4 vs_position; +in vec2 vs_uv; + #include "PowerScaling/powerScaling_fs.hglsl" #include "fragment.glsl" @@ -43,7 +45,7 @@ in vec4 vs_position; Fragment getFragment() { Fragment frag; - frag.color = vec4(1,1,1,1); + frag.color = vec4(vs_uv,1,1); frag.depth = pscDepth(vs_position); return frag;