Skip to content

Commit

Permalink
Surround mode: Make vertical field of view adjustable
Browse files Browse the repository at this point in the history
Based on ideas by Github user ArsenicBismuth in Github pull request #36.

Adjust VFOV with the mouse wheel to zoom in and out, and reset the view with 'Z'.

This also fixes the bug that the aspect ratio for surround mode depended on the view port; it should always be 2:1.
  • Loading branch information
marlam committed Dec 26, 2024
1 parent 1ce91fe commit 1e59d93
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 10 deletions.
8 changes: 8 additions & 0 deletions doc/bino-manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ Bino is a video player with a focus on 3D and Virtual Reality:

Set surround mode (360, 180, off).

- `--surround-vfov` *degrees*

Set surround vertical field of view (default 50, range 5-115).

- `-S`, `--swap-eyes`

Swap left/right eye.
Expand Down Expand Up @@ -307,6 +311,10 @@ The following commands are supported:

Set the given output mode. See the command line option `--output` for a list of modes.

- `set-surround-vfov` *degrees*

Set surround vertical field of view (default 50, range 5-115).

- `set-swap-eyes` `on`|`off`

Set left/right eye swap.
Expand Down
10 changes: 10 additions & 0 deletions src/commandinterpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,16 @@ void CommandInterpreter::processNextCommand()
if (gui)
gui->setOutputMode(outputMode);
}
} else if (cmd.startsWith("set-surround-vfov ")) {
bool ok;
float surroundVerticalFOV = cmd.mid(18).toFloat(&ok);
if (!ok || surroundVerticalFOV < 5.0f || surroundVerticalFOV > 115.0f) {
LOG_FATAL("%s", qPrintable(tr("Invalid argument in %1 line %2").arg(_file.fileName()).arg(_lineIndex)));
} else {
Gui* gui = Gui::instance();
if (gui)
gui->setSurroundVerticalFieldOfView(surroundVerticalFOV);
}
} else if (cmd == "play") {
Bino::instance()->play();
} else if (cmd == "stop") {
Expand Down
22 changes: 20 additions & 2 deletions src/gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ void Gui::addBinoAction(QAction* action, QMenu* menu)

static Gui* GuiSingleton = nullptr;

Gui::Gui(OutputMode outputMode, bool fullscreen) :
Gui::Gui(OutputMode outputMode, float surroundVerticalFOV, bool fullscreen) :
QMainWindow(),
_widget(new Widget(outputMode, this)),
_widget(new Widget(outputMode, surroundVerticalFOV, this)),
_contextMenu(new QMenu(this))
{
setWindowTitle("Bino");
Expand Down Expand Up @@ -442,6 +442,11 @@ Gui::Gui(OutputMode outputMode, bool fullscreen) :
_viewToggleSwapEyesAction->setCheckable(true);
connect(_viewToggleSwapEyesAction, SIGNAL(triggered()), this, SLOT(viewToggleSwapEyes()));
addBinoAction(_viewToggleSwapEyesAction, viewMenu);
viewMenu->addSeparator();
_viewResetSurroundAction = new QAction(tr("Reset surround view"), this);
_viewResetSurroundAction->setShortcuts({ Qt::Key_Z });
connect(_viewResetSurroundAction, SIGNAL(triggered()), this, SLOT(viewResetSurround()));
addBinoAction(_viewResetSurroundAction, viewMenu);

QMenu* helpMenu = addBinoMenu(tr("&Help"));
QAction* helpAboutAction = new QAction(tr("&About..."), this);
Expand Down Expand Up @@ -839,6 +844,12 @@ void Gui::viewToggleSwapEyes()
_widget->update();
}

void Gui::viewResetSurround()
{
_widget->resetSurroundView();
_widget->update();
}

void Gui::helpAbout()
{
QMessageBox::about(this, tr("About Bino"),
Expand Down Expand Up @@ -938,6 +949,7 @@ void Gui::updateActions()
}

SurroundMode surroundMode = Bino::instance()->assumeSurroundMode();
_viewResetSurroundAction->setEnabled(surroundMode != Surround_Off);
for (int i = 0; i < _3dSurroundActionGroup->actions().size(); i++) {
QAction* a = _3dSurroundActionGroup->actions()[i];
a->setChecked(a->data().toInt() == int(surroundMode));
Expand Down Expand Up @@ -980,6 +992,12 @@ void Gui::setOutputMode(OutputMode mode)
_widget->update();
}

void Gui::setSurroundVerticalFieldOfView(float vfov)
{
_widget->setSurroundVerticalFieldOfView(vfov);
_widget->update();
}

void Gui::setFullscreen(bool f)
{
if (f && !(windowState() & Qt::WindowFullScreen)) {
Expand Down
5 changes: 4 additions & 1 deletion src/gui.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ Q_OBJECT
QAction* _mediaSeekBwd10MinsAction;
QAction* _viewToggleFullscreenAction;
QAction* _viewToggleSwapEyesAction;
QAction* _viewResetSurroundAction;

QMenu* addBinoMenu(const QString& title);
void addBinoAction(QAction* action, QMenu* menu);
Expand Down Expand Up @@ -94,6 +95,7 @@ public slots:
void mediaSeekBwd10Mins();
void viewToggleFullscreen();
void viewToggleSwapEyes();
void viewResetSurround();
void helpAbout();

void updateActions();
Expand All @@ -107,10 +109,11 @@ public slots:
virtual void moveEvent(QMoveEvent*) override;

public:
Gui(OutputMode outputMode, bool fullscreen);
Gui(OutputMode outputMode, float surroundVerticalFOV, bool fullscreen);

static Gui* instance();

void setOutputMode(OutputMode mode);
void setSurroundVerticalFieldOfView(float vfov);
void setFullscreen(bool f);
};
14 changes: 13 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,9 @@ int main(int argc, char* argv[])
parser.addOption({ "surround",
QCommandLineParser::tr("Set surround mode (%1).").arg("360, 180, off"),
"mode" });
parser.addOption({ "surround-vfov",
QCommandLineParser::tr("Set surround vertical field of view (default 50, range 5-115)."),
"degrees" });
parser.addOption({ { "S", "swap-eyes" },
QCommandLineParser::tr("Swap left/right eye.") });
parser.addOption({ { "f", "fullscreen" },
Expand Down Expand Up @@ -261,6 +264,15 @@ int main(int argc, char* argv[])
return 1;
}
}
float surroundVerticalFOV = 50.0f;
if (parser.isSet("surround-vfov")) {
bool ok;
surroundVerticalFOV = parser.value("surround-vfov").toFloat(&ok);
if (!ok || surroundVerticalFOV < 5.0f || surroundVerticalFOV > 115.0f) {
LOG_FATAL("%s", qPrintable(QCommandLineParser::tr("Invalid argument for option %1").arg("--surround-vfov")));
return 1;
}
}
InputMode inputMode = Input_Unknown;
if (parser.isSet("input")) {
bool ok;
Expand Down Expand Up @@ -745,7 +757,7 @@ int main(int argc, char* argv[])
return 1;
#endif
} else {
Gui gui(outputMode, parser.isSet("fullscreen"));
Gui gui(outputMode, surroundVerticalFOV, parser.isSet("fullscreen"));
gui.show();
// wait for several seconds to process all events before starting
// the playlist, because otherwise playing might be finished before
Expand Down
30 changes: 26 additions & 4 deletions src/widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@

static const QSize SizeBase(16, 9);

Widget::Widget(OutputMode outputMode, QWidget* parent) :
Widget::Widget(OutputMode outputMode, float surroundVerticalFOV, QWidget* parent) :
QOpenGLWidget(parent),
_sizeHint(0.5f * SizeBase),
_outputMode(outputMode),
Expand All @@ -52,6 +52,8 @@ Widget::Widget(OutputMode outputMode, QWidget* parent) :
_surroundHorizontalAngleCurrent(0.0f),
_surroundVerticalAngleCurrent(0.0f)
{
setSurroundVerticalFieldOfView(surroundVerticalFOV);
_surroundVerticalFOVDefault = _surroundVerticalFOV; // to make sure clamping was applied
setUpdateBehavior(QOpenGLWidget::PartialUpdate);
setMouseTracking(true);
setMinimumSize(8, 8);
Expand Down Expand Up @@ -79,6 +81,20 @@ void Widget::setOutputMode(enum OutputMode mode)
_outputMode = mode;
}

void Widget::setSurroundVerticalFieldOfView(float vfov)
{
_surroundVerticalFOV = qBound(5.0f, vfov, 115.0f);
}

void Widget::resetSurroundView()
{
_surroundVerticalFOV = _surroundVerticalFOVDefault;
_surroundHorizontalAngleBase = 0.0f;
_surroundVerticalAngleBase = 0.0f;
_surroundHorizontalAngleCurrent = 0.0f;
_surroundVerticalAngleCurrent = 0.0f;
}

QSize Widget::sizeHint() const
{
return _sizeHint;
Expand Down Expand Up @@ -287,9 +303,9 @@ void Widget::paintGL()
QMatrix4x4 orientationMatrix;
QMatrix4x4 viewMatrix;
if (Bino::instance()->assumeSurroundMode() != Surround_Off) {
float verticalVieldOfView = qDegreesToRadians(50.0f);
float aspectRatio = float(width) / height;
float top = qTan(verticalVieldOfView * 0.5f);
float verticalFieldOfView = qDegreesToRadians(_surroundVerticalFOV);
float aspectRatio = 2.0f; // always 2:1 for surround video!
float top = qTan(verticalFieldOfView * 0.5f);
float bottom = -top;
float right = top * aspectRatio;
float left = -right;
Expand Down Expand Up @@ -420,6 +436,12 @@ void Widget::mouseMoveEvent(QMouseEvent* e)
}
}

void Widget::wheelEvent(QWheelEvent* e)
{
setSurroundVerticalFieldOfView(_surroundVerticalFOV - e->angleDelta().y() / 120.0f);
update();
}

void Widget::mediaChanged(PlaylistEntry)
{
_inSurroundMovement = false;
Expand Down
9 changes: 7 additions & 2 deletions src/widget.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* This file is part of Bino, a 3D video player.
*
* Copyright (C) 2022
* Copyright (C) 2022, 2023, 2024
* Martin Lambers <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
Expand Down Expand Up @@ -39,6 +39,8 @@ Q_OBJECT
bool _openGLStereo; // is this widget in quad-buffered stereo mode?
int _alternatingLastView; // last view displayed in Mode_Alternating (0 or 1)

float _surroundVerticalFOVDefault;
float _surroundVerticalFOV;
bool _inSurroundMovement;
QPointF _surroundMovementStart;
float _surroundHorizontalAngleBase;
Expand All @@ -55,11 +57,13 @@ Q_OBJECT
void rebuildDisplayPrgIfNecessary(OutputMode outputMode);

public:
Widget(OutputMode outputMode, QWidget* parent = nullptr);
Widget(OutputMode outputMode, float surroundVerticalFOV, QWidget* parent = nullptr);

bool isOpenGLStereo() const;
OutputMode outputMode() const;
void setOutputMode(OutputMode mode);
void setSurroundVerticalFieldOfView(float vfov);
void resetSurroundView();

virtual QSize sizeHint() const override;
virtual void initializeGL() override;
Expand All @@ -70,6 +74,7 @@ Q_OBJECT
virtual void mousePressEvent(QMouseEvent* e) override;
virtual void mouseReleaseEvent(QMouseEvent* e) override;
virtual void mouseMoveEvent(QMouseEvent* e) override;
virtual void wheelEvent(QWheelEvent* e) override;

public slots:
void mediaChanged(PlaylistEntry entry);
Expand Down

0 comments on commit 1e59d93

Please sign in to comment.