From 18a87ef99e41e33b53524264d87458c794e4e7d8 Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Fri, 17 Oct 2014 12:20:23 +0200 Subject: [PATCH] Added ScreenLog - Added first version of a ScreenLog mechanism - Moved the info box to the upper left corner - Added Ubuntu fonts - Made RenderEngine a PropertyOwner with _showInfo and _showScreenLog as bool properties that can be edited through Lua. --- include/openspace/rendering/renderengine.h | 10 +- include/openspace/util/constants.h | 6 + include/openspace/util/screenlog.h | 67 +++++++++ openspace-data | 2 +- openspace.cfg | 3 +- src/abuffer/abuffer.cpp | 4 +- src/engine/openspaceengine.cpp | 5 + src/rendering/renderengine.cpp | 161 ++++++++++++++------- src/util/screenlog.cpp | 51 +++++++ 9 files changed, 248 insertions(+), 61 deletions(-) create mode 100644 include/openspace/util/screenlog.h create mode 100644 src/util/screenlog.cpp diff --git a/include/openspace/rendering/renderengine.h b/include/openspace/rendering/renderengine.h index 8859f7a0c1..ea99843de0 100644 --- a/include/openspace/rendering/renderengine.h +++ b/include/openspace/rendering/renderengine.h @@ -33,12 +33,15 @@ #include #include +#include +#include +#include namespace openspace { class Camera; -class RenderEngine { +class RenderEngine: public properties::PropertyOwner { public: RenderEngine(); ~RenderEngine(); @@ -74,6 +77,11 @@ private: Camera* _mainCamera; SceneGraph* _sceneGraph; ABuffer* _abuffer; + ScreenLog* _log; + + properties::BoolProperty _showInfo; + properties::BoolProperty _showScreenLog; + void generateGlslConfig(); }; diff --git a/include/openspace/util/constants.h b/include/openspace/util/constants.h index 49e8787045..5825956674 100644 --- a/include/openspace/util/constants.h +++ b/include/openspace/util/constants.h @@ -30,6 +30,12 @@ namespace openspace { namespace constants { +namespace fonts { + const std::string keySGCT = "SGCTFont"; + const std::string keyMono = "UbuntuMono"; + const std::string keyLight = "UbuntuLight"; +} // namespace fonts + namespace configurationmanager { const std::string keyPaths = "Paths"; const std::string keyConfigSgct = "SGCTConfig"; diff --git a/include/openspace/util/screenlog.h b/include/openspace/util/screenlog.h new file mode 100644 index 0000000000..b6ce0b8908 --- /dev/null +++ b/include/openspace/util/screenlog.h @@ -0,0 +1,67 @@ +/***************************************************************************************** + * * + * 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 +#include +#include +#include // pair + +namespace openspace { + +class ScreenLog : public ghoul::logging::Log { +public: + //typedef std::tuple LogEntry; + + struct LogEntry { + LogEntry(ghoul::logging::LogManager::LogLevel l, double t, std::string ts, std::string c, std::string m) : level(l), timeStamp(t), timeString(ts), category(c), message(m) {}; + ghoul::logging::LogManager::LogLevel level; + double timeStamp; + std::string timeString; + std::string category; + std::string message; + }; + + typedef std::vector::iterator iterator; + typedef std::vector::const_iterator const_iterator; + typedef std::vector::reverse_iterator reverse_iterator; + typedef std::vector::const_reverse_iterator const_reverse_iterator; + + typedef std::pair range; + typedef std::pair const_range; + + const size_t MaximumSize = 1000; + + ScreenLog(); + + virtual void log(ghoul::logging::LogManager::LogLevel level, const std::string& category, + const std::string& message); + + const_range last(size_t n = 10); + +private: + + std::vector _entries; + +}; +} \ No newline at end of file diff --git a/openspace-data b/openspace-data index 4d3fc5402c..d415918525 160000 --- a/openspace-data +++ b/openspace-data @@ -1 +1 @@ -Subproject commit 4d3fc5402c0f4fe271dbff7f437423cd956245c8 +Subproject commit d415918525c1ec8ca4486d520bb01844e97ce4b6 diff --git a/openspace.cfg b/openspace.cfg index a010b5f459..9567b7fcfa 100644 --- a/openspace.cfg +++ b/openspace.cfg @@ -7,7 +7,8 @@ return { TESTDIR = "${BASE_PATH}/src/tests", CONFIG = "${BASE_PATH}/config", CACHE = "${BASE_PATH}/cache", - TEMPORARY = "${BASE_PATH}/tmp" + TEMPORARY = "${BASE_PATH}/tmp", + FONTS = "${OPENSPACE_DATA}/fonts" }, SpiceKernel = { Time = "${OPENSPACE_DATA}/spice/naif0010.tls", diff --git a/src/abuffer/abuffer.cpp b/src/abuffer/abuffer.cpp index 74cd43521d..93abff5ae3 100644 --- a/src/abuffer/abuffer.cpp +++ b/src/abuffer/abuffer.cpp @@ -190,7 +190,7 @@ bool ABuffer::updateShader() { _fragmentShaderPath); if( ! resolveShader) { - LERROR("Resolve shader not updated"); + LWARNING("ABuffer shader not updated"); return false; } @@ -207,7 +207,7 @@ bool ABuffer::updateShader() { delete _resolveShader; _resolveShader = resolveShader; - LDEBUG("Successfully updated shader!"); + LINFO("Successfully updated ABuffer shader!"); return true; } diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index ec002b70cf..2bf45020bf 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -330,6 +330,11 @@ bool OpenSpaceEngine::initialize() { _engine->scriptEngine().runScriptFile(absoluteScriptPath); } + // Load a light and a monospaced font + sgct_text::FontManager::instance()->setDefaultFontPath(absPath("${FONTS}/")); + sgct_text::FontManager::instance()->addFont(constants::fonts::keyMono, "ubuntu-font-family/UbuntuMono-R.ttf"); + sgct_text::FontManager::instance()->addFont(constants::fonts::keyLight, "ubuntu-font-family/Ubuntu-L.ttf"); + return true; } diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index 0558d9003a..0343ac84fc 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -30,6 +30,7 @@ #include // We need to decide where this is set +#include #include #include #include "sgct.h" @@ -70,9 +71,13 @@ int printImage(lua_State* L) { RenderEngine::RenderEngine() : _mainCamera(nullptr) - , _sceneGraph(nullptr) - , _abuffer(nullptr) + , _sceneGraph(nullptr) + , _abuffer(nullptr) + , _log(nullptr) + , _showInfo("info", "Display info", true) + , _showScreenLog("log", "Display screen log", true) { + setName("renderEngine"); } RenderEngine::~RenderEngine() @@ -178,6 +183,9 @@ bool RenderEngine::initializeGL() _abuffer->initialize(); + _log = new ScreenLog(); + ghoul::logging::LogManager::ref().addLog(_log); + // successful init return true; } @@ -253,61 +261,102 @@ void RenderEngine::render() // Print some useful information on the master viewport sgct::SGCTWindow* w = sgct::Engine::instance()->getActiveWindowPtr(); if (sgct::Engine::instance()->isMaster() && ! w->isUsingFisheyeRendering()) { -// Apple usually has retina screens -#ifdef __APPLE__ -#define FONT_SIZE 18 -#else -#define FONT_SIZE 10 -#endif - - - const glm::vec2 scaling = _mainCamera->scaling(); - const glm::vec3 viewdirection = _mainCamera->viewDirection(); - const psc position = _mainCamera->position(); - const psc origin = OsEng.interactionHandler().getOrigin(); - const PowerScaledScalar pssl = (position - origin).length(); - - /* GUI PRINT */ - - std::string&& time = Time::ref().currentTimeUTC().c_str(); - Freetype::print( - sgct_text::FontManager::instance()->getFont("SGCTFont", FONT_SIZE), - FONT_SIZE, FONT_SIZE * 18, "Date: %s", time.c_str() - ); - Freetype::print( - sgct_text::FontManager::instance()->getFont("SGCTFont", FONT_SIZE), - FONT_SIZE, FONT_SIZE * 16, "Avg. Frametime: %.10f", sgct::Engine::instance()->getAvgDt() - ); - Freetype::print( - sgct_text::FontManager::instance()->getFont("SGCTFont", FONT_SIZE), - FONT_SIZE, FONT_SIZE * 14, "Drawtime: %.10f", sgct::Engine::instance()->getDrawTime() - ); - Freetype::print( - sgct_text::FontManager::instance()->getFont("SGCTFont", FONT_SIZE), - FONT_SIZE, FONT_SIZE * 12, "Frametime: %.10f", sgct::Engine::instance()->getDt() - ); - Freetype::print( - sgct_text::FontManager::instance()->getFont("SGCTFont", FONT_SIZE), - FONT_SIZE, FONT_SIZE * 10, "Origin: (%.5f, %.5f, %.5f, %.5f)", origin[0], - origin[1], origin[2], origin[3]); - Freetype::print( - sgct_text::FontManager::instance()->getFont("SGCTFont", FONT_SIZE), - FONT_SIZE, FONT_SIZE * 8, "Camera position: (%.5f, %.5f, %.5f, %.5f)", - position[0], position[1], position[2], position[3]); - Freetype::print( - sgct_text::FontManager::instance()->getFont("SGCTFont", FONT_SIZE), - FONT_SIZE, FONT_SIZE * 6, "Distance to origin: (%.15f, %.2f)", pssl[0], - pssl[1]); - Freetype::print( - sgct_text::FontManager::instance()->getFont("SGCTFont", FONT_SIZE), - FONT_SIZE, FONT_SIZE * 4, "View direction: (%.3f, %.3f, %.3f)", - viewdirection[0], viewdirection[1], viewdirection[2]); - Freetype::print( - sgct_text::FontManager::instance()->getFont("SGCTFont", FONT_SIZE), - FONT_SIZE, FONT_SIZE * 2, "Scaling: (%.10f, %.2f)", scaling[0], scaling[1]); - - } + + // TODO: Adjust font_size properly when using retina screen + const int font_size = 8; + const int font_with = font_size*0.7; + const sgct_text::Font* fontLight = sgct_text::FontManager::instance()->getFont(constants::fonts::keyLight, font_size); + const sgct_text::Font* fontMono = sgct_text::FontManager::instance()->getFont(constants::fonts::keyMono, font_size); + + if (_showInfo) { + const sgct_text::Font* font = fontMono; + int x1, xSize, y1, ySize; + sgct::Engine::instance()->getActiveWindowPtr()->getCurrentViewportPixelCoords(x1, y1, xSize, ySize); + int startY = ySize - 2 * font_size; + const glm::vec2 scaling = _mainCamera->scaling(); + const glm::vec3 viewdirection = _mainCamera->viewDirection(); + const psc position = _mainCamera->position(); + const psc origin = OsEng.interactionHandler().getOrigin(); + const PowerScaledScalar pssl = (position - origin).length(); + + // GUI PRINT +// Using a macro to shorten line length and increase readability +#define PrintText(i, format, ...) Freetype::print(font, 10, startY - font_size * i * 2, format, __VA_ARGS__); + int i = 0; + PrintText(i++, "Date: %s", Time::ref().currentTimeUTC().c_str()); + PrintText(i++, "Avg. Frametime: %.5f", sgct::Engine::instance()->getAvgDt()); + PrintText(i++, "Drawtime: %.5f", sgct::Engine::instance()->getDrawTime()); + PrintText(i++, "Frametime: %.5f", sgct::Engine::instance()->getDt()); + PrintText(i++, "Origin: (% .5f, % .5f, % .5f, % .5f)", origin[0], origin[1], origin[2], origin[3]); + PrintText(i++, "Cam pos: (% .5f, % .5f, % .5f, % .5f)", position[0], position[1], position[2], position[3]); + PrintText(i++, "View dir: (% .5f, % .5f, % .5f)", viewdirection[0], viewdirection[1], viewdirection[2]); + PrintText(i++, "Cam->origin: (% .15f, % .4f)", pssl[0], pssl[1]); + PrintText(i++, "Scaling: (% .5f, % .5f)", scaling[0], scaling[1]); +#undef PrintText + } + + if (_showScreenLog) + { + const sgct_text::Font* font = fontLight; + const int max = 10; + const int category_length = 20; + const int msg_length = 120; + const double ttl = 10.0; + auto entries = _log->last(max); + + const glm::vec4 white(1, 1, 1, 1); + const glm::vec4 red(1, 0, 0, 1); + const glm::vec4 yellow(1, 1, 0, 1); + const glm::vec4 green(0, 1, 0, 1); + const glm::vec4 blue(0, 0, 1, 1); + + size_t nr = 1; + for (auto it = entries.first; it != entries.second; ++it) { + const ScreenLog::LogEntry* e = &(*it); + + const double t = sgct::Engine::instance()->getTime(); + double diff = t - e->timeStamp; + + // Since all log entries are ordered, once one is exceeding TTL, all have + if (diff > ttl) + break; + + float alpha = 1; + float ttf = ttl - 5.0; + if (diff > ttf) { + diff = diff - ttf; + float p = 0.8 - diff / ttf; + alpha = (p <= 0.0) ? 0.0 : pow(p, 0.3); + } + + // Since all log entries are ordered, once one exceeds alpha, all have + if (alpha <= 0.0) + break; + + std::string lvl = "(" + ghoul::logging::LogManager::stringFromLevel(e->level) + ")"; + Freetype::print(font, 10, font_size * nr * 2, white*alpha, + "%-14s %s%s", // Format + e->timeString.c_str(), // Time string + e->category.substr(0, category_length).c_str(), // Category string (up to category_length) + e->category.length() > 20 ? "..." : ""); // Pad category with "..." if exceeds category_length + + glm::vec4 color = white; + if (e->level == ghoul::logging::LogManager::LogLevel::Debug) + color = green; + if (e->level == ghoul::logging::LogManager::LogLevel::Warning) + color = yellow; + if (e->level == ghoul::logging::LogManager::LogLevel::Error) + color = red; + if (e->level == ghoul::logging::LogManager::LogLevel::Fatal) + color = blue; + + Freetype::print(font, 10 + 39 * font_with, font_size * nr * 2, color*alpha, "%s", lvl.c_str()); + Freetype::print(font, 10 + 53 * font_with, font_size * nr * 2, white*alpha, "%s", e->message.substr(0, msg_length).c_str()); + ++nr; + } + } #endif + } } diff --git a/src/util/screenlog.cpp b/src/util/screenlog.cpp new file mode 100644 index 0000000000..5e972692b1 --- /dev/null +++ b/src/util/screenlog.cpp @@ -0,0 +1,51 @@ +/***************************************************************************************** + * * + * 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 + +#include // sgct::Engine::instance()->getTime() + +namespace openspace { + +ScreenLog::ScreenLog() {} + +void ScreenLog::log(ghoul::logging::LogManager::LogLevel level, const std::string& category, const std::string& message) { + if (level >= ghoul::logging::LogManager::LogLevel::Info) + _entries.emplace_back(level, sgct::Engine::instance()->getTime(), Log::getTimeString(), category, message); + + // Once reaching maximum size, reduce to half + if (_entries.size() > MaximumSize) { + _entries.erase(_entries.begin(), _entries.begin() + MaximumSize / 2); + } +} + +ScreenLog::const_range ScreenLog::last(size_t n) { + if (_entries.size() > n) { + return std::make_pair(_entries.rbegin(), _entries.rbegin() + n); + } else { + return std::make_pair(_entries.rbegin(), _entries.rend()); + } +} + +} \ No newline at end of file