Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,8 @@ set(mmapper_SRCS
opengl/OpenGL.cpp
opengl/OpenGL.h
opengl/UboManager.h
opengl/Weather.cpp
opengl/Weather.h
opengl/OpenGLConfig.cpp
opengl/OpenGLConfig.h
opengl/OpenGLTypes.cpp
Expand Down Expand Up @@ -444,10 +446,14 @@ set(mmapper_SRCS
opengl/legacy/Shaders.h
opengl/legacy/SimpleMesh.cpp
opengl/legacy/SimpleMesh.h
opengl/legacy/TFO.cpp
opengl/legacy/TFO.h
opengl/legacy/VAO.cpp
opengl/legacy/VAO.h
opengl/legacy/VBO.cpp
opengl/legacy/VBO.h
opengl/legacy/WeatherMeshes.cpp
opengl/legacy/WeatherMeshes.h
parser/Abbrev.cpp
parser/Abbrev.h
parser/AbstractParser-Actions.cpp
Expand Down
15 changes: 15 additions & 0 deletions src/configuration/configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,9 @@ ConstString KEY_THEME = "Theme";
ConstString KEY_TLS_ENCRYPTION = "TLS encryption";
ConstString KEY_USE_INTERNAL_EDITOR = "Use internal editor";
ConstString KEY_USE_TRILINEAR_FILTERING = "Use trilinear filtering";
ConstString KEY_WEATHER_ATMOSPHERE_INTENSITY = "weather.atmosphereIntensity";
ConstString KEY_WEATHER_PRECIPITATION_INTENSITY = "weather.precipitationIntensity";
ConstString KEY_WEATHER_TIME_OF_DAY_INTENSITY = "weather.todIntensity";
ConstString KEY_WINDOW_GEOMETRY = "Window Geometry";
ConstString KEY_WINDOW_STATE = "Window State";
ConstString KEY_BELL_AUDIBLE = "Bell audible";
Expand Down Expand Up @@ -662,6 +665,14 @@ void Configuration::CanvasSettings::read(const QSettings &conf)
advanced.verticalAngle.set(conf.value(KEY_3D_VERTICAL_ANGLE, 450).toInt());
advanced.horizontalAngle.set(conf.value(KEY_3D_HORIZONTAL_ANGLE, 0).toInt());
advanced.layerHeight.set(conf.value(KEY_3D_LAYER_HEIGHT, 15).toInt());

weatherAtmosphereIntensity.set(conf.value(KEY_WEATHER_ATMOSPHERE_INTENSITY, 50).toInt());
weatherPrecipitationIntensity.set(conf.value(KEY_WEATHER_PRECIPITATION_INTENSITY, 50).toInt());
weatherTimeOfDayIntensity.set(conf.value(KEY_WEATHER_TIME_OF_DAY_INTENSITY, 50).toInt());

weatherAtmosphereIntensity.clamp(0, 100);
weatherPrecipitationIntensity.clamp(0, 100);
weatherTimeOfDayIntensity.clamp(0, 100);
}

void Configuration::AccountSettings::read(const QSettings &conf)
Expand Down Expand Up @@ -859,6 +870,10 @@ void Configuration::CanvasSettings::write(QSettings &conf) const
conf.setValue(KEY_3D_VERTICAL_ANGLE, advanced.verticalAngle.get());
conf.setValue(KEY_3D_HORIZONTAL_ANGLE, advanced.horizontalAngle.get());
conf.setValue(KEY_3D_LAYER_HEIGHT, advanced.layerHeight.get());

conf.setValue(KEY_WEATHER_ATMOSPHERE_INTENSITY, weatherAtmosphereIntensity.get());
conf.setValue(KEY_WEATHER_PRECIPITATION_INTENSITY, weatherPrecipitationIntensity.get());
conf.setValue(KEY_WEATHER_TIME_OF_DAY_INTENSITY, weatherTimeOfDayIntensity.get());
}

void Configuration::AccountSettings::write(QSettings &conf) const
Expand Down
6 changes: 5 additions & 1 deletion src/configuration/configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,12 +184,16 @@ class NODISCARD Configuration final

MMapper::Array<int, 3> mapRadius{100, 100, 100};

NamedConfig<int> weatherAtmosphereIntensity{"WEATHER_ATMOSPHERE_INTENSITY", 50};
NamedConfig<int> weatherPrecipitationIntensity{"WEATHER_PRECIPITATION_INTENSITY", 50};
NamedConfig<int> weatherTimeOfDayIntensity{"WEATHER_TIME_OF_DAY_INTENSITY", 50};

struct NODISCARD Advanced final
{
NamedConfig<bool> use3D{"MMAPPER_3D", true};
NamedConfig<bool> autoTilt{"MMAPPER_AUTO_TILT", true};
NamedConfig<bool> printPerfStats{"MMAPPER_GL_PERFSTATS", IS_DEBUG_BUILD};
FixedPoint<0> maximumFps{4, 300, 60};
FixedPoint<0> maximumFps{4, 240, 60};

// 5..90 degrees
FixedPoint<1> fov{50, 900, 765};
Expand Down
38 changes: 37 additions & 1 deletion src/display/FrameManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,16 @@

#include <QOpenGLWindow>

FrameManager::FrameManager(QOpenGLWindow &window, QObject *parent)
FrameManager::FrameManager(QOpenGLWindow &window, Legacy::UboManager &uboManager, QObject *parent)
: QObject(parent)
, m_window(window)
, m_uboManager(uboManager)
{
m_uboManager.registerRebuildFunction(Legacy::SharedVboEnum::TimeBlock,
[this](Legacy::Functions &gl) {
m_uboManager.sync<Legacy::SharedVboEnum::TimeBlock>(gl);
});

updateMinFrameTime();
setConfig().canvas.advanced.maximumFps.registerChangeCallback(m_configLifetime, [this]() {
updateMinFrameTime();
Expand All @@ -25,6 +31,11 @@ FrameManager::FrameManager(QOpenGLWindow &window, QObject *parent)
requestFrame();
}

FrameManager::~FrameManager()
{
m_uboManager.unregisterRebuildFunction(Legacy::SharedVboEnum::TimeBlock);
}

void FrameManager::registerCallback(const Signal2Lifetime &lifetime, AnimationCallback callback)
{
m_callbacks.push_back({lifetime.getObj(), std::move(callback)});
Expand Down Expand Up @@ -105,10 +116,35 @@ std::optional<FrameManager::Frame> FrameManager::beginFrame()
}
m_dirty = false;

// Calculate delta time
float deltaTime = 0.0f;
if (hasLastUpdate) {
const auto elapsed = now - m_lastUpdateTime;
deltaTime = std::chrono::duration<float>(elapsed).count();
}
m_lastUpdateTime = now;

// Cap deltaTime for simulation to match map movement during dragging and avoid quantization jitter.
// Cap at 1.0s to avoid huge jumps after window focus loss or lag, while supporting low FPS.
auto lastFrameDeltaTime = std::min(deltaTime, 1.0f);

// Refresh internal struct for UBO
m_elapsedTime += lastFrameDeltaTime;
auto &timeBlock = m_uboManager.get<Legacy::SharedVboEnum::TimeBlock>();
timeBlock.time = glm::vec4(m_elapsedTime, lastFrameDeltaTime, 0.0f, 0.0f);

if (lastFrameDeltaTime > 0.0f) {
m_uboManager.invalidate(Legacy::SharedVboEnum::TimeBlock);
}

return Frame(*this);
}

float FrameManager::getElapsedTime() const
{
return m_elapsedTime;
}

void FrameManager::onHeartbeat()
{
if (!needsHeartbeat()) {
Expand Down
14 changes: 10 additions & 4 deletions src/display/FrameManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "../global/RAII.h"
#include "../global/RuleOf5.h"
#include "../global/Signal2.h"
#include "../opengl/UboManager.h"

#include <chrono>
#include <functional>
Expand Down Expand Up @@ -60,8 +61,8 @@ class FrameManager final : public QObject
QTimer m_heartbeatTimer;
QOpenGLWindow &m_window;
bool m_dirty = true;

friend class TestFrameManager;
float m_elapsedTime = 0.0f;
Legacy::UboManager &m_uboManager;

public:
/**
Expand All @@ -86,9 +87,15 @@ class FrameManager final : public QObject
};

public:
explicit FrameManager(QOpenGLWindow &window, QObject *parent = nullptr);
explicit FrameManager(QOpenGLWindow &window,
Legacy::UboManager &uboManager,
QObject *parent = nullptr);
~FrameManager() override;
DELETE_CTORS_AND_ASSIGN_OPS(FrameManager);

public:
NODISCARD float getElapsedTime() const;

public:
/**
* @brief Register a callback that will be executed once per heartbeat.
Expand Down Expand Up @@ -122,7 +129,6 @@ class FrameManager final : public QObject
void recordFramePainted();
void updateMinFrameTime();
void cleanupExpiredCallbacks();
NODISCARD std::chrono::nanoseconds getJitterTolerance() const;
NODISCARD std::chrono::nanoseconds getTimeUntilNextFrame() const;

private slots:
Expand Down
36 changes: 18 additions & 18 deletions src/display/MapCanvasData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,26 @@ MapCanvasInputState::MapCanvasInputState(PrespammedPath &prespammedPath)

MapCanvasInputState::~MapCanvasInputState() = default;

MapCanvasViewport::~MapCanvasViewport() = default;

const glm::mat4 &MapCanvasViewport::getViewProj() const
{
if (m_viewProjDirty) {
const int w = width();
const int h = height();
if (w > 0 && h > 0) {
const float zoomScale = getTotalScaleFactor();
const auto size = glm::ivec2(w, h);
m_viewProj = (!m_viewportConfig.use3D)
? ProjectionUtils::calculateViewProjOld(getScroll(),
size,
zoomScale,
getCurrentLayer())
: ProjectionUtils::calculateViewProj(m_viewportConfig,
getScroll(),
size,
zoomScale,
getCurrentLayer());
m_viewProjDirty = false;
}
const int w = width();
const int h = height();
if (m_viewProjDirty && w > 0 && h > 0) {
const float zoomScale = getTotalScaleFactor();
const auto size = glm::ivec2(w, h);
m_viewProj = (!m_viewportConfig.use3D)
? ProjectionUtils::calculateViewProjOld(getScroll(),
size,
zoomScale,
getCurrentLayer())
: ProjectionUtils::calculateViewProj(m_viewportConfig,
getScroll(),
size,
zoomScale,
getCurrentLayer());
m_viewProjDirty = false;
}
return m_viewProj;
}
Expand Down
26 changes: 20 additions & 6 deletions src/display/MapCanvasData.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,19 +94,28 @@ struct NODISCARD MapCanvasViewport
private:
QWindow &m_window;

protected:
mutable int m_lastWidth = 0;
mutable int m_lastHeight = 0;

private:
mutable glm::mat4 m_viewProj{1.f};
mutable bool m_viewProjDirty = true;
glm::vec2 m_scroll{0.f};
ScaleFactor m_scaleFactor;
int m_currentLayer = 0;
ViewportConfig m_viewportConfig;
mutable bool m_viewProjDirty = true;

public:
explicit MapCanvasViewport(QWindow &window)
: m_window{window}
{}

virtual ~MapCanvasViewport();

protected:
virtual void onViewProjDirty() const {}

public:
NODISCARD auto width() const { return m_window.width(); }
NODISCARD auto height() const { return m_window.height(); }
Expand All @@ -117,36 +126,41 @@ struct NODISCARD MapCanvasViewport
{
if (m_scroll != scroll) {
m_scroll = scroll;
m_viewProjDirty = true;
markViewProjDirty();
}
}

NODISCARD const ScaleFactor &getScaleFactor() const { return m_scaleFactor; }
void setScaleFactor(const ScaleFactor &scaleFactor)
{
m_scaleFactor = scaleFactor;
m_viewProjDirty = true;
markViewProjDirty();
}

NODISCARD int getCurrentLayer() const { return m_currentLayer; }
void setCurrentLayer(const int layer)
{
if (m_currentLayer != layer) {
m_currentLayer = layer;
m_viewProjDirty = true;
markViewProjDirty();
}
}

void markViewProjDirty() { m_viewProjDirty = true; }
void markViewProjDirty()
{
m_viewProjDirty = true;
onViewProjDirty();
}
void setViewportConfig(const ViewportConfig &config)
{
m_viewportConfig = config;
m_viewProjDirty = true;
markViewProjDirty();
}
void setMvpExtern(const glm::mat4 &mvp) const
{
m_viewProj = mvp;
m_viewProjDirty = false;
onViewProjDirty();
}

NODISCARD const glm::mat4 &getViewProj() const;
Expand Down
1 change: 0 additions & 1 deletion src/display/ProjectionUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ glm::mat4 calculateViewProjOld(const glm::vec2 &scrollPos,
const int /*currentLayer*/)
{
constexpr float FIXED_VIEW_DISTANCE = 60.f;
constexpr float ROOM_Z_SCALE = 7.f;
constexpr auto baseSize = static_cast<float>(ProjectionUtils::BASESIZE);

const float swp = zoomScale * baseSize / static_cast<float>(size.x);
Expand Down
1 change: 1 addition & 0 deletions src/display/ProjectionUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ struct ViewportConfig
namespace ProjectionUtils {

static constexpr const int BASESIZE = 528; // REVISIT: Why this size? 16*33 isn't special.
constexpr float ROOM_Z_SCALE = 7.f;

/**
* @brief Calculate the pitch (vertical angle) in degrees, accounting for auto-tilt if enabled.
Expand Down
Loading
Loading