Skip to content

Commit

Permalink
Add an option to scale camera speed to the simulation size
Browse files Browse the repository at this point in the history
Close: #50
  • Loading branch information
bpe2 committed Oct 31, 2024
1 parent 41b8bee commit c22d40f
Show file tree
Hide file tree
Showing 14 changed files with 768 additions and 567 deletions.
2 changes: 1 addition & 1 deletion src/render/camera/ArcCamera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ void ArcCamera::handleKeyRelease(const int key) {
}

void ArcCamera::move(const float deltaTime) {
const auto velocity = moveSpeed * deltaTime;
const auto velocity = moveSpeed * moveSpeedSizeScale * deltaTime;
const auto cameraDirection = glm::normalize(position - target);
const auto right = glm::normalize(glm::cross(cameraDirection, world_up));
const auto up = glm::normalize(glm::cross(right, cameraDirection));
Expand Down
1 change: 1 addition & 0 deletions src/render/camera/ArcCamera.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class ArcCamera {
const glm::vec3 world_up{0.0f, 1.0f, 0.0f};
float mouseTurnSpeed;
float moveSpeed;
float moveSpeedSizeScale{1.0f};
float keyboardTurnSpeed;
float fieldOfView;
float zoomSpeed{0.5f}; // TODO: Make configurable
Expand Down
14 changes: 11 additions & 3 deletions src/render/camera/Camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,8 @@ glm::mat4 Camera::view_matrix() const {
return glm::lookAt(position, position + front, up);
}

void Camera::move(float delta_time) {
auto velocity = move_speed * delta_time;
void Camera::move(const float delta_time) {
const auto velocity = move_speed * moveSpeedSizeScale * delta_time;

if (active.front_back == active_directions::direction::forward)
position += front * velocity;
Expand All @@ -164,7 +164,7 @@ void Camera::move(float delta_time) {
if (active.turn == active_directions::side::none)
return;

auto turnVelocity = turnSpeed * delta_time;
const auto turnVelocity = turnSpeed * delta_time;
if (active.turn == active_directions::side::left)
yaw -= turnVelocity;
else if (active.turn == active_directions::side::right)
Expand All @@ -191,6 +191,14 @@ void Camera::mouse_move(float delta_x, float delta_y) {
update();
}

float Camera::getMoveSpeedSizeScale() const {
return moveSpeedSizeScale;
}

void Camera::setMoveSpeedSizeScale(const float value) {
moveSpeedSizeScale = value;
}

Camera::move_state Camera::getMobility() const {
return mobility;
}
Expand Down
4 changes: 4 additions & 0 deletions src/render/camera/Camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class Camera {
float yaw{-90.0f};
float pitch{0.0f};

float moveSpeedSizeScale{1.0f};
float move_speed{0.05f};
float turnSpeed{0.1};
float mouseTurnSpeed{0.5f};
Expand Down Expand Up @@ -133,6 +134,9 @@ class Camera {
void move(float delta_time);
void mouse_move(float delta_x, float delta_y);

[[nodiscard]] float getMoveSpeedSizeScale() const;
void setMoveSpeedSizeScale(float value);

[[nodiscard]] glm::vec3 get_position() const;
void setPosition(const glm::vec3 &value);

Expand Down
8 changes: 8 additions & 0 deletions src/render/helper/Floor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,12 @@ texture_id Floor::getTextureId() const {
return *mesh.getMaterial().textureId;
}

float Floor::getSize() const {
return size;
}

void Floor::setSize(const float value) {
size = value;
}

} // namespace netsimulyzer
4 changes: 4 additions & 0 deletions src/render/helper/Floor.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class Floor {
Mesh mesh;
glm::vec3 position{0.0f};
glm::mat4 model{1.0f};
float size{100.0f};

public:
explicit Floor(Mesh mesh);
Expand All @@ -64,6 +65,9 @@ class Floor {
[[nodiscard]] const Mesh &getMesh() const;
[[nodiscard]] texture_id getTextureId() const;

[[nodiscard]] float getSize() const;
void setSize(float value);

void render();
};

Expand Down
2 changes: 2 additions & 0 deletions src/render/renderer/Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,8 @@ void Renderer::resize(Floor &f, float size) {

glBindBuffer(GL_ARRAY_BUFFER, renderInfo.vbo);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(floorVertices), reinterpret_cast<const void *>(floorVertices));

f.setSize(size);
}

CoordinateGrid::RenderInfo Renderer::allocateCoordinateGrid(float size, int stepSize) {
Expand Down
2 changes: 2 additions & 0 deletions src/settings/SettingsManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class SettingsManager {
LastLoadPath,
ResourcePath,
MoveSpeed,
AutoScaleMoveSpeed,
KeyboardTurnSpeed,
MouseTurnSpeed,
FieldOfView,
Expand Down Expand Up @@ -192,6 +193,7 @@ class SettingsManager {
{Key::LastLoadPath, {"application/lastLoadPath", {}}},
{Key::ResourcePath, {"resources/resourcePath", {}}},
{Key::MoveSpeed, {"camera/moveSpeed", 0.02f}},
{Key::AutoScaleMoveSpeed, {"camera/autoScaleMoveSpeed", false}},
{Key::KeyboardTurnSpeed, {"camera/keyboardTurnSpeed", 0.1f}},
{Key::MouseTurnSpeed, {"camera/mouseTurnSpeed", 0.5f}},
{Key::FieldOfView, {"camera/fieldOfView", 45.0f}},
Expand Down
8 changes: 4 additions & 4 deletions src/window/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,7 @@ MainWindow::MainWindow() : QMainWindow() {
settingsDialog.show();
});

QObject::connect(&settingsDialog, &SettingsDialog::moveSpeedChanged, [this](float value) {
scene.getCamera().setMoveSpeed(value);
scene.getArcCamera().moveSpeed = value;
});
QObject::connect(&settingsDialog, &SettingsDialog::moveSpeedChanged, &scene, &SceneWidget::setCameraMoveSpeed);

QObject::connect(&settingsDialog, &SettingsDialog::keyboardTurnSpeedChanged, [this](float value) {
scene.getCamera().setTurnSpeed(value);
Expand Down Expand Up @@ -253,6 +250,9 @@ MainWindow::MainWindow() : QMainWindow() {
scene.setCameraType(SettingsManager::CameraTypeFromInt(value));
});

QObject::connect(&settingsDialog, &SettingsDialog::autoscaleMoveSpeedChanged, &scene,
&SceneWidget::setAutoscaleCameraMoveSpeed);

QObject::connect(&settingsDialog, &SettingsDialog::renderFloorChanged, &scene, &SceneWidget::setFloorRenderState);

QObject::connect(&settingsDialog, &SettingsDialog::backgroundColorChanged, &scene, &SceneWidget::setClearColor);
Expand Down
67 changes: 67 additions & 0 deletions src/window/scene/SceneWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,51 @@ void SceneWidget::handleUndoEvents() {
emit selectedItemUpdated();
}

float SceneWidget::getCameraAutoscale() const {
// Scale camera movement so we may cross the whole simulation
// In about 20 real life seconds
const auto cameraSpeed = settings.get<float>(SettingsManager::Key::MoveSpeed).value();
// 20 seconds in ms
constexpr auto timeToCrossInMs = 20.0f * 1000.0f;

// 'Crossing the simulation' means from corner to corner
//
// (pretend this is square)
//
// `newSize`
// origin --> *_____
// |\ |
// | \ |
// | \ | `newSize`
// | \|
// ------
// since `newSize` is distance from the origin
//
// `newSize`
// *_____
// \ |
// `newSize`*sq(2) \ |
// \ | `newSize`
// \|
//
// so, distance to the origin from one corner is `newSize` * sq(2)
// we have to double that to get corner to corner
// so, the total diagonal distance is `newSize * std::sqrt(2.0f) * 2.0f`
return floor->getSize() * std::sqrt(2.0f) * 2.0f / (cameraSpeed * timeToCrossInMs);
}

void SceneWidget::applyAutoscaleCameraSpeed() {
if (autoscaleCameraMoveSpeed) {
const auto speedScale = getCameraAutoscale();
camera.setMoveSpeedSizeScale(speedScale);
arcCamera.moveSpeedSizeScale = speedScale;
return;
}

camera.setMoveSpeedSizeScale(1.0f);
arcCamera.moveSpeedSizeScale = 1.0f;
}

void SceneWidget::initializeGL() {
if (!initializeOpenGLFunctions()) {
std::cerr << "Failed OpenGL functions\n";
Expand Down Expand Up @@ -665,6 +710,8 @@ SceneWidget::SceneWidget(QWidget *parent, const Qt::WindowFlags &f) : QOpenGLWid
}

setResourcePath(resourceDirSetting.value());

applyAutoscaleCameraSpeed();
}

SceneWidget::~SceneWidget() {
Expand All @@ -686,11 +733,17 @@ void SceneWidget::setConfiguration(parser::GlobalConfiguration configuration) {

// Don't resize beneath the default
if (newSize > 100.0f) {
makeCurrent();
renderer.resize(*floor, newSize + 50.0f); // Give the new size a bit of extra overrun
renderer.resize(*coordinateGrid, newSize + 50.0f, settings.get<int>(SettingsManager::Key::RenderGridStep).value());
doneCurrent();
}

// time step handled by the MainWindow

const auto speedScale = getCameraAutoscale();
camera.setMoveSpeedSizeScale(speedScale);
arcCamera.moveSpeedSizeScale = speedScale;
}

void SceneWidget::reset() {
Expand All @@ -705,6 +758,9 @@ void SceneWidget::reset() {
selectedNode.reset();
fontManager.reset();
simulationTime = 0.0;

camera.setMoveSpeedSizeScale(1.0f);
arcCamera.moveSpeedSizeScale = 1.0f;
}

void SceneWidget::add(const std::vector<parser::Area> &areaModels, const std::vector<parser::Building> &buildingModels,
Expand Down Expand Up @@ -981,6 +1037,17 @@ void SceneWidget::setLabelScale(float value) {
labelScale = value;
}

void SceneWidget::setCameraMoveSpeed(const float value) {
camera.setMoveSpeed(value);
arcCamera.moveSpeed = value;
applyAutoscaleCameraSpeed();
}

void SceneWidget::setAutoscaleCameraMoveSpeed(const bool value) {
autoscaleCameraMoveSpeed = value;
applyAutoscaleCameraSpeed();
}

void SceneWidget::setSelectedNode(unsigned int nodeId) {
if (nodes.find(nodeId) == nodes.end()) {
std::cerr << "Node with ID: " << nodeId << " selected, but not found in `nodes`, ignoring!\n";
Expand Down
15 changes: 15 additions & 0 deletions src/window/scene/SceneWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ class SceneWidget : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core {
// that OpenGL can accept
std::array<float, 3> clearColorGl{static_cast<float>(clearColor.redF()), static_cast<float>(clearColor.greenF()),
static_cast<float>(clearColor.blueF())};
bool autoscaleCameraMoveSpeed = settings.get<bool>(SettingsManager::Key::AutoScaleMoveSpeed).value();

std::unique_ptr<PickingFramebuffer> pickingFbo;

Expand Down Expand Up @@ -154,6 +155,17 @@ class SceneWidget : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core {
void handleEvents();
void handleUndoEvents();

/**
* Calculate the autoscale multiplier for
* the camera to cross the scenario in a
* fixed about of time
*
* @return
* The value to use for the camera move speed multiplier
*/
float getCameraAutoscale() const;
void applyAutoscaleCameraSpeed();

protected:
void initializeGL() override;
void paintGL() override;
Expand Down Expand Up @@ -337,6 +349,9 @@ class SceneWidget : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core {
*/
void setLabelScale(float value);

void setCameraMoveSpeed(float value);
void setAutoscaleCameraMoveSpeed(bool value);

void setSelectedNode(unsigned int nodeId);
void clearSelectedNode();

Expand Down
26 changes: 26 additions & 0 deletions src/window/settings/SettingsDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ void SettingsDialog::loadSettings() {
const auto cameraType = settings.get<SettingsManager::CameraType>(Key::RenderCameraType).value();
ui.comboCameraType->setCurrentIndex(ui.comboCameraType->findData(static_cast<int>(cameraType)));

ui.checkBoxScaleMoveSpeed->setChecked(settings.get<bool>(Key::AutoScaleMoveSpeed).value());

ui.checkBoxSkybox->setChecked(settings.get<bool>(Key::RenderSkybox).value());
ui.checkBoxFloor->setChecked(settings.get<bool>(Key::RenderFloor).value());

Expand Down Expand Up @@ -171,6 +173,10 @@ SettingsDialog::SettingsDialog(QWidget *parent) : QDialog(parent) {

loadSettings();

ui.sliderMoveSpeed->setEnabled(!ui.checkBoxScaleMoveSpeed->isChecked());
QObject::connect(ui.checkBoxScaleMoveSpeed, &QCheckBox::stateChanged, this,
&SettingsDialog::autoscaleMoveSpeedToggled);

QObject::connect(ui.buttonResetTheme, &QPushButton::clicked, this, &SettingsDialog::defaultWindowTheme);
QObject::connect(ui.buttonResetMoveSpeed, &QPushButton::clicked, this, &SettingsDialog::defaultMoveSpeed);
QObject::connect(ui.buttonResetKeyboardTurnSpeed, &QPushButton::clicked, this,
Expand All @@ -192,6 +198,8 @@ SettingsDialog::SettingsDialog(QWidget *parent) : QDialog(parent) {
QObject::connect(ui.buttonResetSkybox, &QPushButton::clicked, this, &SettingsDialog::defaultEnableSkybox);
QObject::connect(ui.buttonResetFloor, &QPushButton::clicked, this, &SettingsDialog::defaultEnableFloor);
QObject::connect(ui.buttonResetCameraType, &QPushButton::clicked, this, &SettingsDialog::defaultCameraType);
QObject::connect(ui.buttonResetMoveSpeedScale, &QPushButton::clicked, this,
&SettingsDialog::defaultAutoscaleMoveSpeed);
QObject::connect(ui.buttonResetBackgroundColor, &QPushButton::clicked, this, &SettingsDialog::defaultBackgroundColor);
QObject::connect(ui.buttonResetSamples, &QPushButton::clicked, this, &SettingsDialog::defaultSamples);
QObject::connect(ui.buttonResetBuildingRender, &QPushButton::clicked, this, &SettingsDialog::defaultBuildingEffect);
Expand Down Expand Up @@ -256,6 +264,7 @@ void SettingsDialog::dialogueButtonClicked(QAbstractButton *button) {
ui.buttonResetSkybox->click();
ui.buttonResetFloor->click();
ui.buttonResetCameraType->click();
ui.buttonResetMoveSpeedScale->click();
ui.buttonResetBackgroundColor->click();
ui.buttonResetSamples->click();
ui.buttonResetBuildingRender->click();
Expand Down Expand Up @@ -286,6 +295,12 @@ void SettingsDialog::dialogueButtonClicked(QAbstractButton *button) {
emit cameraTypeChanged(static_cast<int>(cameraType));
}

const auto autoscaleMoveSpeed = settings.get<bool>(Key::AutoScaleMoveSpeed).value();
if (autoscaleMoveSpeed != ui.checkBoxScaleMoveSpeed->isChecked()) {
settings.set(Key::AutoScaleMoveSpeed, autoscaleMoveSpeed);
emit autoscaleMoveSpeedChanged(ui.checkBoxScaleMoveSpeed->isChecked());
}

const auto moveSpeed = static_cast<float>(ui.sliderMoveSpeed->value()) / moveSpeedScale;
settings.set(Key::MoveSpeed, moveSpeed);
emit moveSpeedChanged(moveSpeed);
Expand Down Expand Up @@ -504,6 +519,14 @@ void SettingsDialog::dialogueButtonClicked(QAbstractButton *button) {
}
}

void SettingsDialog::autoscaleMoveSpeedToggled(const int state) {
ui.sliderMoveSpeed->setEnabled(state != Qt::CheckState::Checked);
if (state == Qt::CheckState::Checked) {
ui.sliderMoveSpeed->setValue(
static_cast<int>(*settings.get<float>(SettingsManager::Key::MoveSpeed) * moveSpeedScale));
}
}

void SettingsDialog::defaultWindowTheme() {
const auto defaultTheme = settings.getDefault<SettingsManager::WindowTheme>(SettingsManager::Key::WindowTheme);
ui.comboTheme->setCurrentIndex(ui.comboTheme->findData(static_cast<int>(defaultTheme)));
Expand Down Expand Up @@ -553,6 +576,9 @@ void SettingsDialog::defaultCameraType() {
settings.getDefault<SettingsManager::CameraType>(SettingsManager::Key::RenderCameraType);
ui.comboCameraType->setCurrentIndex(ui.comboCameraType->findData(static_cast<int>(defaultCameraType)));
}
void SettingsDialog::defaultAutoscaleMoveSpeed() {
ui.checkBoxScaleMoveSpeed->setChecked(settings.getDefault<bool>(SettingsManager::Key::AutoScaleMoveSpeed));
}

void SettingsDialog::defaultEnableFloor() {
ui.checkBoxFloor->setChecked(settings.getDefault<bool>(SettingsManager::Key::RenderFloor));
Expand Down
13 changes: 13 additions & 0 deletions src/window/settings/SettingsDialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ class SettingsDialog : public QDialog {
*/
void dialogueButtonClicked(QAbstractButton *button);

void autoscaleMoveSpeedToggled(int state);

/**
* Set the Window Theme combobox to the default value
*/
Expand Down Expand Up @@ -149,6 +151,8 @@ class SettingsDialog : public QDialog {
*/
void defaultCameraType();

void defaultAutoscaleMoveSpeed();

/**
* Set the Floor checkbox to the default value
*/
Expand Down Expand Up @@ -365,6 +369,15 @@ class SettingsDialog : public QDialog {
*/
void cameraTypeChanged(int value);

/**
* Signal emitted when the user changes the Autoscale Move Speed toggle.
*
* @param value
* True if the user wants to use Autoscaling for movement speed
* false otherwise
*/
void autoscaleMoveSpeedChanged(bool value);

/**
* Signal emitted when the user changes the
* Floor render state
Expand Down
Loading

0 comments on commit c22d40f

Please sign in to comment.