From 516e6b36ba37b446131312145011221acec8130f Mon Sep 17 00:00:00 2001 From: Erik Broberg Date: Wed, 22 Jun 2016 21:07:47 -0400 Subject: [PATCH 1/9] Use std::make_shared instead of new --- .../globebrowsing/chunk/chunkedlodglobe.cpp | 4 +-- modules/globebrowsing/chunk/chunkrenderer.cpp | 36 ++++++++----------- 2 files changed, 16 insertions(+), 24 deletions(-) diff --git a/modules/globebrowsing/chunk/chunkedlodglobe.cpp b/modules/globebrowsing/chunk/chunkedlodglobe.cpp index fb26a85320..8534f537ec 100644 --- a/modules/globebrowsing/chunk/chunkedlodglobe.cpp +++ b/modules/globebrowsing/chunk/chunkedlodglobe.cpp @@ -58,8 +58,8 @@ namespace openspace { size_t segmentsPerPatch, std::shared_ptr tileProviderManager) : _ellipsoid(ellipsoid) - , _leftRoot(new ChunkNode(Chunk(this, LEFT_HEMISPHERE_INDEX))) - , _rightRoot(new ChunkNode(Chunk(this, RIGHT_HEMISPHERE_INDEX))) + , _leftRoot(std::make_unique(Chunk(this, LEFT_HEMISPHERE_INDEX))) + , _rightRoot(std::make_unique(Chunk(this, RIGHT_HEMISPHERE_INDEX))) , minSplitDepth(2) , maxSplitDepth(22) , _savedCamera(nullptr) diff --git a/modules/globebrowsing/chunk/chunkrenderer.cpp b/modules/globebrowsing/chunk/chunkrenderer.cpp index eac705c079..0081659cd6 100644 --- a/modules/globebrowsing/chunk/chunkrenderer.cpp +++ b/modules/globebrowsing/chunk/chunkrenderer.cpp @@ -62,23 +62,18 @@ namespace openspace { : _tileProviderManager(tileProviderManager) , _grid(grid) { - _globalRenderingShaderProvider = std::shared_ptr - (new LayeredTextureShaderProvider( + _globalRenderingShaderProvider = std::make_shared( "GlobalChunkedLodPatch", "${MODULE_GLOBEBROWSING}/shaders/globalchunkedlodpatch_vs.glsl", - "${MODULE_GLOBEBROWSING}/shaders/globalchunkedlodpatch_fs.glsl")); + "${MODULE_GLOBEBROWSING}/shaders/globalchunkedlodpatch_fs.glsl"); - _localRenderingShaderProvider = std::shared_ptr - (new LayeredTextureShaderProvider( + _localRenderingShaderProvider = std::make_shared( "LocalChunkedLodPatch", "${MODULE_GLOBEBROWSING}/shaders/localchunkedlodpatch_vs.glsl", - "${MODULE_GLOBEBROWSING}/shaders/localchunkedlodpatch_fs.glsl")); + "${MODULE_GLOBEBROWSING}/shaders/localchunkedlodpatch_fs.glsl"); - _globalProgramUniformHandler = std::shared_ptr - (new LayeredTextureShaderUniformIdHandler()); - - _localProgramUniformHandler = std::shared_ptr - (new LayeredTextureShaderUniformIdHandler()); + _globalProgramUniformHandler = std::make_shared(); + _localProgramUniformHandler = std::make_shared(); } @@ -170,8 +165,7 @@ namespace openspace { LayeredTextures::NUM_TEXTURE_CATEGORIES> tileProviders; LayeredTexturePreprocessingData layeredTexturePreprocessingData; - for (size_t category = 0; category < LayeredTextures::NUM_TEXTURE_CATEGORIES; category++) - { + for (size_t category = 0; category < LayeredTextures::NUM_TEXTURE_CATEGORIES; category++) { tileProviders[category] = _tileProviderManager->getActivatedLayerCategory( LayeredTextures::TextureCategory(category)); @@ -209,19 +203,16 @@ namespace openspace { ghoul::opengl::TextureUnit blendTexture1; ghoul::opengl::TextureUnit blendTexture2; }; - std::array, - LayeredTextures::NUM_TEXTURE_CATEGORIES> texUnits; + std::array, LayeredTextures::NUM_TEXTURE_CATEGORIES> texUnits; for (size_t category = 0; category < LayeredTextures::NUM_TEXTURE_CATEGORIES; category++) { texUnits[category].resize(tileProviders[category].size()); } // Go through all the categories - for (size_t category = 0; category < LayeredTextures::NUM_TEXTURE_CATEGORIES; category++) - { + for (size_t category = 0; category < LayeredTextures::NUM_TEXTURE_CATEGORIES; category++) { // Go through all the providers in this category int i = 0; - for (auto it = tileProviders[category].begin(); it != tileProviders[category].end(); it++) - { + for (auto it = tileProviders[category].begin(); it != tileProviders[category].end(); it++) { auto tileProvider = it->get(); // Get the texture that should be used for rendering @@ -272,8 +263,9 @@ namespace openspace { // Go through all the height maps and set depth tranforms int i = 0; - for (auto it = tileProviders[LayeredTextures::HeightMaps].begin(); - it != tileProviders[LayeredTextures::HeightMaps].end(); it++) { + auto it = tileProviders[LayeredTextures::HeightMaps].begin(); + auto end = tileProviders[LayeredTextures::HeightMaps].end(); + for (; it != end; it++) { auto tileProvider = *it; TileDepthTransform depthTransform = tileProvider->depthTransform(); @@ -314,7 +306,7 @@ namespace openspace { break; } } - if(performAnyBlending) { + if (performAnyBlending) { float distanceScaleFactor = chunk.owner()->lodScaleFactor * ellipsoid.minimumRadius(); programObject->setUniform("cameraPosition", vec3(data.camera.positionVec3())); programObject->setUniform("distanceScaleFactor", distanceScaleFactor); From a6baa5107a31cf1efb9c5a036652d003fc685498 Mon Sep 17 00:00:00 2001 From: Erik Broberg Date: Thu, 23 Jun 2016 20:02:24 -0400 Subject: [PATCH 2/9] Add test if GeodeticPatch contains a Geodetic2 --- modules/globebrowsing/geometry/geodetic2.cpp | 7 ++++++- modules/globebrowsing/geometry/geodetic2.h | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/modules/globebrowsing/geometry/geodetic2.cpp b/modules/globebrowsing/geometry/geodetic2.cpp index 5ff5601887..66279858eb 100644 --- a/modules/globebrowsing/geometry/geodetic2.cpp +++ b/modules/globebrowsing/geometry/geodetic2.cpp @@ -181,7 +181,12 @@ namespace openspace { return _center.lon + _halfSize.lon; } - + + bool GeodeticPatch::contains(const Geodetic2& p) const { + Geodetic2 diff = _center - p; + return glm::abs(diff.lat) <= _halfSize.lat && glm::abs(diff.lon) <= _halfSize.lon; + } + Scalar GeodeticPatch::edgeLatitudeNearestEquator() const { return _center.lat + _halfSize.lat * (isNorthern() ? -1 : 1); diff --git a/modules/globebrowsing/geometry/geodetic2.h b/modules/globebrowsing/geometry/geodetic2.h index 786970aeb7..5286ed8995 100644 --- a/modules/globebrowsing/geometry/geodetic2.h +++ b/modules/globebrowsing/geometry/geodetic2.h @@ -127,6 +127,11 @@ public: Scalar minLon() const; Scalar maxLon() const; + /** + * returns true if the specified coordinate is contained within the patch + */ + bool contains(const Geodetic2& p) const; + /** * Clamps a point to the patch region From e59dd7a391e1068a2994785acf39e71a22880d4e Mon Sep 17 00:00:00 2001 From: Erik Broberg Date: Thu, 23 Jun 2016 20:16:47 -0400 Subject: [PATCH 3/9] Enable finding a ChunkNode in ChunkNode tree based on a Geodetic2 point --- modules/globebrowsing/chunk/chunknode.cpp | 37 +++++++++++++++++++++-- modules/globebrowsing/chunk/chunknode.h | 5 +++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/modules/globebrowsing/chunk/chunknode.cpp b/modules/globebrowsing/chunk/chunknode.cpp index 2efda5a548..2198fc4276 100644 --- a/modules/globebrowsing/chunk/chunknode.cpp +++ b/modules/globebrowsing/chunk/chunknode.cpp @@ -154,6 +154,40 @@ void ChunkNode::reverseBreadthFirst(const std::function& } } +#define CHUNK_NODE_FIND(node, p) \ + while (!node->isLeaf()) { \ + const Geodetic2 center = node->_chunk.surfacePatch().center();\ + int index = 0;\ + if (center.lon < p.lon) {\ + ++index;\ + }\ + if (p.lat < center.lat) {\ + ++index;\ + ++index;\ + }\ + node = &(node->getChild((Quad)index));\ + } + +const ChunkNode& ChunkNode::find(const Geodetic2& location) const { + const ChunkNode* node = this; + CHUNK_NODE_FIND(node, location); + return *node; +} + +ChunkNode& ChunkNode::find(const Geodetic2& location) { + ChunkNode* node = this; + CHUNK_NODE_FIND(node, location); + return *node; +} + +const ChunkNode& ChunkNode::getChild(Quad quad) const { + return *_children[quad]; +} + +ChunkNode& ChunkNode::getChild(Quad quad) { + return *_children[quad]; +} + void ChunkNode::split(int depth) { if (depth > 0 && isLeaf()) { for (size_t i = 0; i < 4; i++) { @@ -180,9 +214,6 @@ void ChunkNode::merge() { ghoul_assert(isLeaf(), "ChunkNode must be leaf after merge"); } -const ChunkNode& ChunkNode::getChild(Quad quad) const { - return *_children[quad]; -} const Chunk& ChunkNode::getChunk() const { return _chunk; diff --git a/modules/globebrowsing/chunk/chunknode.h b/modules/globebrowsing/chunk/chunknode.h index 8ee054ba2b..3968559cee 100644 --- a/modules/globebrowsing/chunk/chunknode.h +++ b/modules/globebrowsing/chunk/chunknode.h @@ -65,8 +65,13 @@ public: void depthFirst(const std::function& f) const; void breadthFirst(const std::function& f) const; void reverseBreadthFirst(const std::function& f) const; + + const ChunkNode& find(const Geodetic2& location) const; + ChunkNode& find(const Geodetic2& location); const ChunkNode& getChild(Quad quad) const; + ChunkNode& getChild(Quad quad); + const Chunk& getChunk() const; bool updateChunkTree(const RenderData& data); From 0c935e5b59173c6fcdb7d9aacbe64b0439e154b2 Mon Sep 17 00:00:00 2001 From: Erik Broberg Date: Thu, 23 Jun 2016 20:23:08 -0400 Subject: [PATCH 4/9] Use current - instead of maximum - chunk level height tiles in ground collision test --- modules/globebrowsing/chunk/chunkedlodglobe.cpp | 12 ++++++++++++ modules/globebrowsing/chunk/chunkedlodglobe.h | 5 +++++ modules/globebrowsing/globes/renderableglobe.cpp | 4 ++-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/modules/globebrowsing/chunk/chunkedlodglobe.cpp b/modules/globebrowsing/chunk/chunkedlodglobe.cpp index 8534f537ec..2c6a5927f7 100644 --- a/modules/globebrowsing/chunk/chunkedlodglobe.cpp +++ b/modules/globebrowsing/chunk/chunkedlodglobe.cpp @@ -52,6 +52,8 @@ namespace openspace { const ChunkIndex ChunkedLodGlobe::LEFT_HEMISPHERE_INDEX = ChunkIndex(0, 0, 1); const ChunkIndex ChunkedLodGlobe::RIGHT_HEMISPHERE_INDEX = ChunkIndex(1, 0, 1); + const GeodeticPatch ChunkedLodGlobe::COVERAGE = GeodeticPatch(0, 0, 90, 180); + ChunkedLodGlobe::ChunkedLodGlobe( const Ellipsoid& ellipsoid, @@ -116,6 +118,16 @@ namespace openspace { return false; } + const ChunkNode& ChunkedLodGlobe::findChunkNode(const Geodetic2 p) const { + ghoul_assert(COVERAGE.contains(p), "Point must be in lat [-90, 90] and lon [-180, 180]"); + return p.lon < COVERAGE.center().lon ? _leftRoot->find(p) : _rightRoot->find(p); + } + + ChunkNode& ChunkedLodGlobe::findChunkNode(const Geodetic2 p) { + ghoul_assert(COVERAGE.contains(p), "Point must be in lat [-90, 90] and lon [-180, 180]"); + return p.lon < COVERAGE.center().lon ? _leftRoot->find(p) : _rightRoot->find(p); + } + int ChunkedLodGlobe::getDesiredLevel(const Chunk& chunk, const RenderData& renderData) const { int desiredLevel = 0; if (debugOptions.levelByProjAreaElseDistance) { diff --git a/modules/globebrowsing/chunk/chunkedlodglobe.h b/modules/globebrowsing/chunk/chunkedlodglobe.h index 4a985effcb..ac01cd7c52 100644 --- a/modules/globebrowsing/chunk/chunkedlodglobe.h +++ b/modules/globebrowsing/chunk/chunkedlodglobe.h @@ -72,6 +72,9 @@ namespace openspace { void render(const RenderData& data) override; void update(const UpdateData& data) override; + const ChunkNode& findChunkNode(const Geodetic2 location) const; + ChunkNode& findChunkNode(const Geodetic2 location); + void setStateMatrix(const glm::dmat3& stateMatrix); bool testIfCullable(const Chunk& chunk, const RenderData& renderData) const; @@ -117,6 +120,8 @@ namespace openspace { void debugRenderChunk(const Chunk& chunk, const glm::dmat4& data) const; + static const GeodeticPatch COVERAGE; + // Covers all negative longitudes std::unique_ptr _leftRoot; diff --git a/modules/globebrowsing/globes/renderableglobe.cpp b/modules/globebrowsing/globes/renderableglobe.cpp index beed4d8794..5042f32153 100644 --- a/modules/globebrowsing/globes/renderableglobe.cpp +++ b/modules/globebrowsing/globes/renderableglobe.cpp @@ -197,8 +197,8 @@ namespace openspace { // Get the uv coordinates to sample from Geodetic2 geodeticPosition = _ellipsoid.cartesianToGeodetic2(position); - int chunkLevel = - tileProvider->getAsyncTileReader()->getTextureDataProvider()->getMaximumLevel(); + int chunkLevel = _chunkedLodGlobe->findChunkNode(geodeticPosition).getChunk().index().level; + ChunkIndex chunkIdx = ChunkIndex(geodeticPosition, chunkLevel); GeodeticPatch patch = GeodeticPatch(chunkIdx); Geodetic2 geoDiffPatch = patch.getCorner(Quad::NORTH_EAST) - patch.getCorner(Quad::SOUTH_WEST); From 064c9a57229a95acf6517ab12fd8540b096b6f4e Mon Sep 17 00:00:00 2001 From: Erik Broberg Date: Fri, 24 Jun 2016 11:44:01 -0400 Subject: [PATCH 5/9] Add templated stats collector to store structured data in tables --- modules/globebrowsing/CMakeLists.txt | 2 + .../globebrowsing/chunk/chunkedlodglobe.cpp | 3 +- modules/globebrowsing/chunk/chunkedlodglobe.h | 5 + .../globebrowsing/other/statscollector.cpp | 34 ++++ modules/globebrowsing/other/statscollector.h | 183 ++++++++++++++++++ 5 files changed, 225 insertions(+), 2 deletions(-) create mode 100644 modules/globebrowsing/other/statscollector.cpp create mode 100644 modules/globebrowsing/other/statscollector.h diff --git a/modules/globebrowsing/CMakeLists.txt b/modules/globebrowsing/CMakeLists.txt index 1c032afb0b..fe23fb01da 100644 --- a/modules/globebrowsing/CMakeLists.txt +++ b/modules/globebrowsing/CMakeLists.txt @@ -63,6 +63,7 @@ set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/other/concurrentjobmanager.h ${CMAKE_CURRENT_SOURCE_DIR}/other/threadpool.h ${CMAKE_CURRENT_SOURCE_DIR}/other/concurrentqueue.h + ${CMAKE_CURRENT_SOURCE_DIR}/other/statscollector.h ) @@ -104,6 +105,7 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/other/lrucache.inl ${CMAKE_CURRENT_SOURCE_DIR}/other/concurrentjobmanager.inl ${CMAKE_CURRENT_SOURCE_DIR}/other/threadpool.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/other/statscollector.cpp ) diff --git a/modules/globebrowsing/chunk/chunkedlodglobe.cpp b/modules/globebrowsing/chunk/chunkedlodglobe.cpp index 2c6a5927f7..e38edca3b1 100644 --- a/modules/globebrowsing/chunk/chunkedlodglobe.cpp +++ b/modules/globebrowsing/chunk/chunkedlodglobe.cpp @@ -78,8 +78,7 @@ namespace openspace { _chunkCullers.push_back(std::make_unique()); _chunkCullers.push_back(std::make_unique(AABB3(vec3(-1, -1, 0), vec3(1, 1, 1e35)))); - - + _chunkEvaluatorByAvailableTiles = std::make_unique(); _chunkEvaluatorByProjectedArea = std::make_unique(); _chunkEvaluatorByDistance = std::make_unique(); diff --git a/modules/globebrowsing/chunk/chunkedlodglobe.h b/modules/globebrowsing/chunk/chunkedlodglobe.h index ac01cd7c52..e781c516c9 100644 --- a/modules/globebrowsing/chunk/chunkedlodglobe.h +++ b/modules/globebrowsing/chunk/chunkedlodglobe.h @@ -44,6 +44,8 @@ #include #include +#include + namespace ghoul { namespace opengl { @@ -146,6 +148,9 @@ namespace openspace { std::shared_ptr _savedCamera; std::shared_ptr _tileProviderManager; + + //std::shared_ptr> _stats; + //StatsTracker stats; }; } // namespace openspace diff --git a/modules/globebrowsing/other/statscollector.cpp b/modules/globebrowsing/other/statscollector.cpp new file mode 100644 index 0000000000..62ee4f6c89 --- /dev/null +++ b/modules/globebrowsing/other/statscollector.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 { + + +} // namespace openspace \ No newline at end of file diff --git a/modules/globebrowsing/other/statscollector.h b/modules/globebrowsing/other/statscollector.h new file mode 100644 index 0000000000..f6d69257e6 --- /dev/null +++ b/modules/globebrowsing/other/statscollector.h @@ -0,0 +1,183 @@ +/***************************************************************************************** + * * + * 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 __STATS_TRACKER_H__ +#define __STATS_TRACKER_H__ + +#include +#include + + +#include +#include +#include +#include +#include + + + +namespace openspace { + + + template + struct StatsRecord : public std::unordered_map { + + }; + + template + struct StatsCollection : public std::vector> { + std::set keys; + }; + + + template class StatsCollector{ + public: + + StatsCollector() = delete; + + StatsCollector(const std::string& filename, bool enabled = true) + : _filename(filename) + //, _writer(writer) + , _enabled(enabled) + { + + }; + + ~StatsCollector() { + if (_data.keys.size() > 0) { + std::cout << "Saving stats to: " << _filename << std::endl; + write(); + } + }; + + void disable() { + _enabled = false; + } + + void enable() { + _enabled = true; + } + + void startNewRecord() { + if (_enabled) { + _data.push_back(StatsRecord()); + } + } + + T& operator[](const std::string& name) { + if (_enabled) { + _data.keys.insert(name); + return _data.back()[name]; + } + else return _dummy; + } + + T previous(const std::string& name) { + if (_enabled && _data.size() > 1) { + return _data[_data.size() - 2][name]; + } + return T(); + } + + + private: + + void write() { + std::string _delimiter = ","; + std::ofstream ofs(_filename); + + // output headers + auto keyIt = _data.keys.begin(); + ofs << *keyIt; + while (++keyIt != _data.keys.end()) { + ofs << _delimiter << *keyIt; + } + ofs << std::endl; + + // output line by line + for (StatsRecord& record : _data) { + // Access every key. Records with no entry will get a default value + keyIt = _data.keys.begin(); + ofs << record[(*keyIt)]; + while (++keyIt != _data.keys.end()) { + ofs << _delimiter << record[(*keyIt)]; + } + ofs << std::endl; + } + ofs.close(); + } + + private: + + + StatsCollection _data; + const std::string _filename; + + bool _enabled; + T _dummy; // used when disabled + }; + + /* + + template + struct StatsCsvWriter { + StatsCsvWriter(const std::string& delimiter) + : _delimiter(delimiter) { }; + + virtual void write(const StatsCollection& stats, const std::string& filename) { + std::ofstream ofs(filename); + + // output headers + auto keyIt = stats.keys.begin(); + ofs << *keyIt; + while (keyIt++ != stats.keys.end()) { + ofs << _delimiter << *keyIt; + } + ofs << std::endl; + + // output line by line + for (const StatsRecord& record : stats) { + // Access every key. Records with no entry will get a default value + auto keyIt = stats.keys.begin(); + ofs << record[*keyIt]; + while (keyIt++ != stats.keys.end()) { + ofs << _delimiter << record[*keyIt]; + } + ofs << std::endl; + } + ofs.close(); + } + + private: + std::string _delimiter; + }; + */ + + +} // namespace openspace + + + + + +#endif // __STATS_TRACKER_H__ \ No newline at end of file From b5c85184da341a14666b6c2bae51c512ea10cb65 Mon Sep 17 00:00:00 2001 From: Erik Broberg Date: Fri, 24 Jun 2016 13:52:30 -0400 Subject: [PATCH 6/9] Restructure StatsCollectors to keep track of both integers and doubles --- modules/globebrowsing/other/statscollector.h | 171 ++++++++++++------- 1 file changed, 114 insertions(+), 57 deletions(-) diff --git a/modules/globebrowsing/other/statscollector.h b/modules/globebrowsing/other/statscollector.h index f6d69257e6..cb3e3c96b2 100644 --- a/modules/globebrowsing/other/statscollector.h +++ b/modules/globebrowsing/other/statscollector.h @@ -50,38 +50,18 @@ namespace openspace { }; - template class StatsCollector{ + template class TemplatedStatsCollector{ public: - StatsCollector() = delete; + TemplatedStatsCollector(bool& enabled, const std::string& delimiter) + : _enabled(enabled) + , _delimiter(delimiter) + , _writePos(0) { }; - StatsCollector(const std::string& filename, bool enabled = true) - : _filename(filename) - //, _writer(writer) - , _enabled(enabled) - { - - }; - - ~StatsCollector() { - if (_data.keys.size() > 0) { - std::cout << "Saving stats to: " << _filename << std::endl; - write(); - } - }; - - void disable() { - _enabled = false; - } - - void enable() { - _enabled = true; - } + ~TemplatedStatsCollector() { }; void startNewRecord() { - if (_enabled) { - _data.push_back(StatsRecord()); - } + _data.push_back(StatsRecord()); } T& operator[](const std::string& name) { @@ -99,42 +79,119 @@ namespace openspace { return T(); } - - private: - - void write() { - std::string _delimiter = ","; - std::ofstream ofs(_filename); - - // output headers - auto keyIt = _data.keys.begin(); - ofs << *keyIt; - while (++keyIt != _data.keys.end()) { - ofs << _delimiter << *keyIt; - } - ofs << std::endl; - - // output line by line - for (StatsRecord& record : _data) { - // Access every key. Records with no entry will get a default value - keyIt = _data.keys.begin(); - ofs << record[(*keyIt)]; - while (++keyIt != _data.keys.end()) { - ofs << _delimiter << record[(*keyIt)]; - } - ofs << std::endl; - } - ofs.close(); + bool hasRecordsToWrite() { + return _writePos < _data.size(); } + void reset() { + _data.clear(); + _writePos = 0; + } + + void writeHeader(std::ostream& os) { + auto keyIt = _data.keys.begin(); + os << *keyIt; + while (++keyIt != _data.keys.end()) { + os << _delimiter << *keyIt; + } + } + + void writeNextRecord(std::ostream& os) { + if (hasRecordsToWrite()) { + // output line by line + StatsRecord& record = _data[_writePos]; + + // Access every key. Records with no entry will get a default value + auto keyIt = _data.keys.begin(); + os << record[(*keyIt)]; + while (++keyIt != _data.keys.end()) { + os << _delimiter << record[(*keyIt)]; + } + + _writePos++; + } + } + + private: - StatsCollection _data; - const std::string _filename; - - bool _enabled; T _dummy; // used when disabled + bool& _enabled; + + size_t _writePos; + std::string _delimiter; + + }; + + class StatsCollector { + + public: + + StatsCollector() = delete; + + StatsCollector(const std::string& filename, const std::string& delimiter = ",", bool enabled = true) + : _filename(filename) + , _enabled(enabled) + , _delimiter(delimiter) + , _hasWrittenHead(false) + , i(TemplatedStatsCollector(_enabled, delimiter)) + , d(TemplatedStatsCollector(_enabled, delimiter)) + { + + }; + + ~StatsCollector() { + dumpToDisk(); + } + + void startNewRecord() { + if (_enabled) { + i.startNewRecord(); + d.startNewRecord(); + } + } + + void disable() { + _enabled = false; + } + + void enable() { + _enabled = true; + } + + void dumpToDisk() { + if (!_hasWrittenHead) { + writeHead(); + } + writeData(); + } + + TemplatedStatsCollector i; + TemplatedStatsCollector d; + + private: + void writeHead() { + std::ofstream ofs(_filename); + i.writeHeader(ofs); ofs << _delimiter; d.writeHeader(ofs); ofs << std::endl; + ofs.close(); + } + + void writeData() { + std::ofstream ofs(_filename, std::ofstream::out | std::ofstream::app); + while (i.hasRecordsToWrite() || d.hasRecordsToWrite()) { + i.writeNextRecord(ofs); ofs << _delimiter; d.writeNextRecord(ofs); + ofs << std::endl; + } + i.reset(); d.reset(); + ofs.close(); + } + + std::string _filename; + std::string _delimiter; + bool _enabled; + bool _hasWrittenHead; + }; /* From b9f3b03af390021a32975e68e9ee89eacf923ff2 Mon Sep 17 00:00:00 2001 From: Erik Broberg Date: Fri, 24 Jun 2016 14:51:25 -0400 Subject: [PATCH 7/9] Fix bug causing StatsCollector to crash during dump to file if a StatsCollection is empty --- modules/globebrowsing/other/statscollector.h | 38 +++++++++++++++----- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/modules/globebrowsing/other/statscollector.h b/modules/globebrowsing/other/statscollector.h index cb3e3c96b2..3caec5b8b2 100644 --- a/modules/globebrowsing/other/statscollector.h +++ b/modules/globebrowsing/other/statscollector.h @@ -61,7 +61,8 @@ namespace openspace { ~TemplatedStatsCollector() { }; void startNewRecord() { - _data.push_back(StatsRecord()); + if(_enabled) + _data.push_back(StatsRecord()); } T& operator[](const std::string& name) { @@ -73,14 +74,18 @@ namespace openspace { } T previous(const std::string& name) { - if (_enabled && _data.size() > 1) { + if (_data.size() > 1) { return _data[_data.size() - 2][name]; } return T(); } + bool hasHeaders() { + return _data.keys.size() > 0; + } + bool hasRecordsToWrite() { - return _writePos < _data.size(); + return _writePos < _data.size() - 1; } void reset() { @@ -103,9 +108,11 @@ namespace openspace { // Access every key. Records with no entry will get a default value auto keyIt = _data.keys.begin(); - os << record[(*keyIt)]; - while (++keyIt != _data.keys.end()) { - os << _delimiter << record[(*keyIt)]; + if (keyIt != _data.keys.end()) { + os << record[(*keyIt)]; + while (++keyIt != _data.keys.end()) { + os << _delimiter << record[(*keyIt)]; + } } _writePos++; @@ -173,14 +180,29 @@ namespace openspace { private: void writeHead() { std::ofstream ofs(_filename); - i.writeHeader(ofs); ofs << _delimiter; d.writeHeader(ofs); ofs << std::endl; + if (i.hasHeaders()) { + i.writeHeader(ofs); + if (d.hasHeaders()) { + ofs << _delimiter; + d.writeHeader(ofs); + } + } + else { + d.writeHeader(ofs); + } + ofs << std::endl; ofs.close(); } void writeData() { std::ofstream ofs(_filename, std::ofstream::out | std::ofstream::app); while (i.hasRecordsToWrite() || d.hasRecordsToWrite()) { - i.writeNextRecord(ofs); ofs << _delimiter; d.writeNextRecord(ofs); + if (i.hasHeaders() && d.hasHeaders()) { + i.writeNextRecord(ofs); ofs << _delimiter; d.writeNextRecord(ofs); + } + else { + i.writeNextRecord(ofs); d.writeNextRecord(ofs); + } ofs << std::endl; } i.reset(); d.reset(); From 6843b37a3d562c7eee3257a0b7ebb11550aa0ca6 Mon Sep 17 00:00:00 2001 From: Erik Broberg Date: Fri, 24 Jun 2016 16:35:35 -0400 Subject: [PATCH 8/9] Add D3 javascript visualization of chunk statistics generated by StatsCollector --- .../globebrowsing/chunk/chunkedlodglobe.cpp | 32 ++++- modules/globebrowsing/chunk/chunkedlodglobe.h | 3 +- monitor/index.html | 114 ++++++++++++++++++ monitor/style.css | 20 +++ 4 files changed, 163 insertions(+), 6 deletions(-) create mode 100644 monitor/index.html create mode 100644 monitor/style.css diff --git a/modules/globebrowsing/chunk/chunkedlodglobe.cpp b/modules/globebrowsing/chunk/chunkedlodglobe.cpp index e38edca3b1..37f6203340 100644 --- a/modules/globebrowsing/chunk/chunkedlodglobe.cpp +++ b/modules/globebrowsing/chunk/chunkedlodglobe.cpp @@ -43,6 +43,8 @@ #define _USE_MATH_DEFINES #include +#include + namespace { const std::string _loggerCat = "ChunkLodGlobe"; } @@ -66,6 +68,7 @@ namespace openspace { , maxSplitDepth(22) , _savedCamera(nullptr) , _tileProviderManager(tileProviderManager) + , stats(StatsCollector(absPath("test_stats"))) { auto geometry = std::make_shared( @@ -84,6 +87,7 @@ namespace openspace { _chunkEvaluatorByDistance = std::make_unique(); _renderer = std::make_unique(geometry, tileProviderManager); + } ChunkedLodGlobe::~ChunkedLodGlobe() { @@ -146,9 +150,23 @@ namespace openspace { desiredLevel = glm::clamp(desiredLevel, minSplitDepth, maxSplitDepth); return desiredLevel; } - void ChunkedLodGlobe::render(const RenderData& data){ + + stats.startNewRecord(); + + + int j2000s = Time::now().unsyncedJ2000Seconds(); + int lastJ2000s = stats.i.previous("time"); + if (j2000s == lastJ2000s) { + stats.disable(); + } + else { + stats.enable(); + } + + stats.i["time"] = j2000s; + minDistToCamera = INFINITY; _leftRoot->updateChunkTree(data); @@ -162,10 +180,16 @@ namespace openspace { // Render function std::function renderJob = [this, &data, &mvp](const ChunkNode& chunkNode) { + stats.i["chunks"]++; const Chunk& chunk = chunkNode.getChunk(); - if (chunkNode.isLeaf() && chunk.isVisible()) { - _renderer->renderChunk(chunkNode.getChunk(), data); - debugRenderChunk(chunk, mvp); + if (chunkNode.isLeaf()){ + stats.i["chunks leafs"]++; + if (chunk.isVisible()) { + stats.i["rendered chunks"]++; + double t0 = Time::now().unsyncedJ2000Seconds(); + _renderer->renderChunk(chunkNode.getChunk(), data); + debugRenderChunk(chunk, mvp); + } } }; diff --git a/modules/globebrowsing/chunk/chunkedlodglobe.h b/modules/globebrowsing/chunk/chunkedlodglobe.h index e781c516c9..56e8d2e39c 100644 --- a/modules/globebrowsing/chunk/chunkedlodglobe.h +++ b/modules/globebrowsing/chunk/chunkedlodglobe.h @@ -117,6 +117,7 @@ namespace openspace { bool levelByProjAreaElseDistance = true; } debugOptions; + StatsCollector stats; private: @@ -149,8 +150,6 @@ namespace openspace { std::shared_ptr _tileProviderManager; - //std::shared_ptr> _stats; - //StatsTracker stats; }; } // namespace openspace diff --git a/monitor/index.html b/monitor/index.html new file mode 100644 index 0000000000..e5c69edb16 --- /dev/null +++ b/monitor/index.html @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/monitor/style.css b/monitor/style.css new file mode 100644 index 0000000000..ebf2021fb5 --- /dev/null +++ b/monitor/style.css @@ -0,0 +1,20 @@ +body { + font: 10px sans-serif; +} + +.axis path, +.axis line { + fill: none; + stroke: #000; + shape-rendering: crispEdges; +} + +.x.axis path { + display: none; +} + +.line { + fill: none; + stroke: steelblue; + stroke-width: 1.5px; +} From 7d80598166aa1ba482eecfedc3d5ed3887204a0a Mon Sep 17 00:00:00 2001 From: Erik Broberg Date: Mon, 27 Jun 2016 13:44:08 -0400 Subject: [PATCH 9/9] Add Mars Viking MDIM21 dataset config --- .../MARS_Viking_MDIM21.xml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 data/scene/debugglobe/map_service_configs/MARS_Viking_MDIM21.xml diff --git a/data/scene/debugglobe/map_service_configs/MARS_Viking_MDIM21.xml b/data/scene/debugglobe/map_service_configs/MARS_Viking_MDIM21.xml new file mode 100644 index 0000000000..cd87af69be --- /dev/null +++ b/data/scene/debugglobe/map_service_configs/MARS_Viking_MDIM21.xml @@ -0,0 +1,19 @@ + + + http://dzw9r5p966egh.cloudfront.net/catalog/Mars_Viking_MDIM21_ClrMosaic_global_232m/1.0.0//default/default028mm/${z}/${y}/${x}.jpg + + + -180.0 + 90 + 180.0 + -90 + 8 + 2 + 1 + top + + EPSG:4326 + 256 + 256 + 3 + \ No newline at end of file