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.
This commit is contained in:
Jonas Strandstedt
2014-10-17 12:20:23 +02:00
parent 13bdd33f7e
commit 18a87ef99e
9 changed files with 248 additions and 61 deletions

View File

@@ -33,12 +33,15 @@
#include <string>
#include <openspace/abuffer/abuffer.h>
#include <openspace/util/screenlog.h>
#include <openspace/properties/propertyowner.h>
#include <openspace/properties/scalarproperty.h>
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();
};

View File

@@ -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";

View File

@@ -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 <ghoul/logging/log.h>
#include <vector>
#include <tuple>
#include <utility> // pair
namespace openspace {
class ScreenLog : public ghoul::logging::Log {
public:
//typedef std::tuple<ghoul::logging::LogManager::LogLevel, std::string, std::string> 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<LogEntry>::iterator iterator;
typedef std::vector<LogEntry>::const_iterator const_iterator;
typedef std::vector<LogEntry>::reverse_iterator reverse_iterator;
typedef std::vector<LogEntry>::const_reverse_iterator const_reverse_iterator;
typedef std::pair<reverse_iterator, reverse_iterator> range;
typedef std::pair<const_reverse_iterator, const_reverse_iterator> 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<LogEntry> _entries;
};
}

View File

@@ -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",

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -30,6 +30,7 @@
#include <openspace/util/time.h>
// We need to decide where this is set
#include <openspace/util/constants.h>
#include <openspace/util/time.h>
#include <openspace/util/spicemanager.h>
#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
}
}

51
src/util/screenlog.cpp Normal file
View File

@@ -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 <openspace/util/screenlog.h>
#include <sgct.h> // 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());
}
}
}