Skip to content

Commit

Permalink
Merge branch 'marlam:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
ThreeDeeJay authored Aug 10, 2024
2 parents 4580d40 + 83e5999 commit ab256c8
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 37 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
# Required: Qt6
find_package(Qt6 6.6.0 REQUIRED COMPONENTS OpenGLWidgets Multimedia LinguistTools)
# Optional: QVR for Virtual Reality support
find_package(QVR 4.0.0 QUIET)
find_package(QVR 4.1.0 QUIET)
if(QVR_FOUND)
add_definitions(-DWITH_QVR)
include_directories(${QVR_INCLUDE_DIRS})
Expand Down
14 changes: 10 additions & 4 deletions doc/bino-manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ Bino is a video player with a focus on 3D and Virtual Reality:

- `--vr-screen` *screen*

Set VR screen geometry, either as a comma-separated list of nine values
representing three 3D coordinates that define a planar screen (bottom left,
bottom right, top left) or as a name of an OBJ file that contains the screen
geometry with texture coordinates.
Set VR screen geometry, either as the special values 'united' or 'intersected', or as a comma-separated list of nine
values representing three 3D coordinates that define a planar screen (bottom left, bottom right, top left), or as a an
aspect ratio followed by the name of an OBJ file that contains the screen geometry with texture coordinates (example:
'16:9,myscreen.obj').

- `--capture`

Expand Down Expand Up @@ -329,6 +329,12 @@ their bottom left, bottom right and top left corners, or to load arbitrary
screen geometry from an OBJ file. The latter case is useful e.g. if you want
Bino's virtual screen to coincide with a curved physical screen.

The `--vr-screen` option also accepts the special values `united` and
`intersected`. This will unite (or intersect) the 2D geometries of all VR windows
at runtime. For example, use `--vr-screen=united --qvr-config=two-screen-stereo.qvr`
for a two-screen stereo setup, where the left view goes on the first screen and
the right view goes on the second screen.

Bino uses QVRs default navigation, which may be based on autodetected
controllers such as the HTC Vive controllers, or on tracking and interaction
hardware configured via QVR for your VR system, or on the mouse and WASDQE keys
Expand Down
59 changes: 43 additions & 16 deletions src/bino.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

static Bino* binoSingleton = nullptr;

Bino::Bino(const Screen& screen, bool swapEyes) :
Bino::Bino(ScreenType screenType, const Screen& screen, bool swapEyes) :
_wantExit(false),
_videoSink(nullptr),
_audioOutput(nullptr),
Expand All @@ -43,6 +43,7 @@ Bino::Bino(const Screen& screen, bool swapEyes) :
_captureSession(nullptr),
_lastFrameInputMode(Input_Unknown),
_lastFrameSurroundMode(Surround_Unknown),
_screenType(screenType),
_screen(screen),
_frameIsNew(false),
_frameWasSerialized(true),
Expand Down Expand Up @@ -499,12 +500,12 @@ SurroundMode Bino::assumeSurroundMode() const

void Bino::serializeStaticData(QDataStream& ds) const
{
ds << _screen;
ds << _screenType << _screen;
}

void Bino::deserializeStaticData(QDataStream& ds)
{
ds >> _screen;
ds >> _screenType >> _screen;
}

void Bino::serializeDynamicData(QDataStream& ds)
Expand Down Expand Up @@ -731,23 +732,20 @@ bool Bino::initProcess()
// Screen geometry
glGenVertexArrays(1, &_screenVao);
glBindVertexArray(_screenVao);
GLuint positionBuf;
glGenBuffers(1, &positionBuf);
glBindBuffer(GL_ARRAY_BUFFER, positionBuf);
glGenBuffers(1, &_positionBuf);
glBindBuffer(GL_ARRAY_BUFFER, _positionBuf);
glBufferData(GL_ARRAY_BUFFER, _screen.positions.size() * sizeof(float),
_screen.positions.constData(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
GLuint texcoordBuf;
glGenBuffers(1, &texcoordBuf);
glBindBuffer(GL_ARRAY_BUFFER, texcoordBuf);
glGenBuffers(1, &_texcoordBuf);
glBindBuffer(GL_ARRAY_BUFFER, _texcoordBuf);
glBufferData(GL_ARRAY_BUFFER, _screen.texcoords.size() * sizeof(float),
_screen.texcoords.constData(), GL_STATIC_DRAW);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
GLuint indexBuf;
glGenBuffers(1, &indexBuf);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
glGenBuffers(1, &_indexBuf);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuf);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
_screen.indices.length() * sizeof(unsigned int),
_screen.indices.constData(), GL_STATIC_DRAW);
Expand All @@ -773,8 +771,8 @@ void Bino::rebuildColorPrgIfNecessary(int planeFormat, bool yuvValueRangeSmall,
colorFS.replace("$VALUE_RANGE_SMALL", yuvValueRangeSmall ? "true" : "false");
colorFS.replace("$YUV_SPACE", QString::number(yuvSpace));
if (isGLES) {
colorVS.prepend("#version 320 es\n");
colorFS.prepend("#version 320 es\n"
colorVS.prepend("#version 310 es\n");
colorFS.prepend("#version 310 es\n"
"precision mediump float;\n");
} else {
colorVS.prepend("#version 330\n");
Expand Down Expand Up @@ -807,8 +805,8 @@ void Bino::rebuildViewPrgIfNecessary(SurroundMode surroundMode, bool nonLinearOu
: "0");
viewFS.replace("$NONLINEAR_OUTPUT", nonLinearOutput ? "true" : "false");
if (isGLES) {
viewVS.prepend("#version 320 es\n");
viewFS.prepend("#version 320 es\n"
viewVS.prepend("#version 310 es\n");
viewFS.prepend("#version 310 es\n"
"precision mediump float;\n");
} else {
viewVS.prepend("#version 330\n");
Expand Down Expand Up @@ -1120,12 +1118,26 @@ void Bino::preRenderProcess(int screenWidth, int screenHeight,
}

void Bino::render(
const QVector3D& unitedScreenBottomLeft, const QVector3D& unitedScreenBottomRight, const QVector3D& unitedScreenTopLeft,
const QVector3D& intersectedScreenBottomLeft, const QVector3D& intersectedScreenBottomRight, const QVector3D& intersectedScreenTopLeft,
const QMatrix4x4& projectionMatrix,
const QMatrix4x4& orientationMatrix,
const QMatrix4x4& viewMatrix,
int view, // 0 = left, 1 = right
int texWidth, int texHeight, unsigned int texture)
{
// Update screen
switch (_screenType) {
case ScreenUnited:
_screen = Screen(unitedScreenBottomLeft, unitedScreenBottomRight, unitedScreenTopLeft);
break;
case ScreenIntersected:
_screen = Screen(intersectedScreenBottomLeft, intersectedScreenBottomRight, intersectedScreenTopLeft);
break;
case ScreenGeometry:
// do nothing
break;
}
// Set up framebuffer object to render into
glBindTexture(GL_TEXTURE_2D, _depthTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, texWidth, texHeight,
Expand Down Expand Up @@ -1246,6 +1258,21 @@ void Bino::render(
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
} else {
glBindVertexArray(_screenVao);
if (_screenType == ScreenUnited || _screenType == ScreenIntersected) {
// the geometry might have changed; re-upload it
glBindBuffer(GL_ARRAY_BUFFER, _positionBuf);
glBufferData(GL_ARRAY_BUFFER, _screen.positions.size() * sizeof(float),
_screen.positions.constData(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, _texcoordBuf);
glBufferData(GL_ARRAY_BUFFER, _screen.texcoords.size() * sizeof(float),
_screen.texcoords.constData(), GL_STATIC_DRAW);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuf);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
_screen.indices.length() * sizeof(unsigned int),
_screen.indices.constData(), GL_STATIC_DRAW);
}
glDrawElements(GL_TRIANGLES, _screen.indices.size(), GL_UNSIGNED_INT, 0);
}
}
Expand Down
14 changes: 12 additions & 2 deletions src/bino.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ class Bino : public QObject, QOpenGLExtraFunctions
{
Q_OBJECT

public:
enum ScreenType {
ScreenUnited, // global 2D united screen given by QVR
ScreenIntersected, // global 2D intersected screen given by QVR
ScreenGeometry // explicit geometry stored in _screen
};

private:
/* Data not directly relevant for rendering */
bool _wantExit;
Expand All @@ -63,6 +70,7 @@ Q_OBJECT
SurroundMode _lastFrameSurroundMode;

/* Static data for rendering, initialized on the main process */
ScreenType _screenType;
Screen _screen;

/* Static data for rendering, initialized in initProcess() */
Expand All @@ -75,7 +83,7 @@ Q_OBJECT
unsigned int _frameTex;
unsigned int _extFrameTex;
unsigned int _subtitleTex;
unsigned int _screenVao;
unsigned int _screenVao, _positionBuf, _texcoordBuf, _indexBuf;
QOpenGLShaderProgram _colorPrg;
int _colorPrgPlaneFormat;
bool _colorPrgYuvValueRangeSmall;
Expand All @@ -98,7 +106,7 @@ Q_OBJECT
void convertFrameToTexture(const VideoFrame& frame, unsigned int frameTex);

public:
Bino(const Screen& screen, bool swapEyes);
Bino(ScreenType screenType, const Screen& screen, bool swapEyes);
virtual ~Bino();

static Bino* instance();
Expand Down Expand Up @@ -178,6 +186,8 @@ Q_OBJECT
float* frameDisplayAspectRatio = nullptr,
bool* surround = nullptr);
void render(
const QVector3D& unitedScreenBottomLeft, const QVector3D& unitedScreenBottomRight, const QVector3D& unitedScreenTopLeft,
const QVector3D& intersectedScreenBottomLeft, const QVector3D& intersectedScreenBottomRight, const QVector3D& intersectedScreenTopLeft,
const QMatrix4x4& projectionMatrix,
const QMatrix4x4& orientationMatrix,
const QMatrix4x4& viewMatrix,
Expand Down
22 changes: 15 additions & 7 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,10 @@ int main(int argc, char* argv[])
parser.addOption({ "vr",
QCommandLineParser::tr("Start in VR mode instead of GUI mode.")});
parser.addOption({ "vr-screen",
QCommandLineParser::tr("Set VR screen geometry, either as a comma-separated list of "
"nine values representing three 3D coordinates that define a planar screen (bottom left, bottom right, top left) "
"or as a name of an OBJ file that contains the screen geometry with texture coordinates."),
QCommandLineParser::tr("Set VR screen geometry, either as the special values 'united' or 'intersected', or "
"as a comma-separated list of nine values representing three 3D coordinates that define a planar screen (bottom left, bottom right, top left), "
"or as a an aspect ratio followed by the name of an OBJ file that contains the screen geometry with texture coordinates "
"(example: '16:9,myscreen.obj')."),
"screen" });
parser.addOption({ "capture",
QCommandLineParser::tr("Capture audio/video input from microphone and camera/screen/window.") });
Expand Down Expand Up @@ -546,30 +547,37 @@ int main(int argc, char* argv[])
}

// Handle the VR Screen
Screen screen;
Bino::ScreenType screenType = Bino::ScreenGeometry;
Screen screen; // default screen for non-VR mode
if (parser.isSet("vr")) {
float screenCenterHeight = 1.76f - 0.15f; // does not matter, never used
#ifdef WITH_QVR
screenCenterHeight = QVRObserverConfig::defaultEyeHeight;
#endif
screen = Screen(
screen = Screen( // default screen for VR mode
QVector3D(-16.0f / 9.0f, -1.0f + screenCenterHeight, -8.0f),
QVector3D(+16.0f / 9.0f, -1.0f + screenCenterHeight, -8.0f),
QVector3D(-16.0f / 9.0f, +1.0f + screenCenterHeight, -8.0f));
if (parser.isSet("vr-screen")) {
QStringList paramList = parser.value("vr-screen").split(',');
float values[9];
if (paramList.length() == 9
if (parser.value("vr-screen") == "united") {
screenType = Bino::ScreenUnited;
} else if (parser.value("vr-screen") == "intersected") {
screenType = Bino::ScreenIntersected;
} else if (paramList.length() == 9
&& 9 == std::sscanf(qPrintable(parser.value("vr-screen")),
"%f,%f,%f,%f,%f,%f,%f,%f,%f",
values + 0, values + 1, values + 2,
values + 3, values + 4, values + 5,
values + 6, values + 7, values + 8)) {
screenType = Bino::ScreenGeometry;
screen = Screen(
QVector3D(values[0], values[1], values[2]),
QVector3D(values[3], values[4], values[5]),
QVector3D(values[6], values[7], values[8]));
} else if (paramList.length() == 2) {
screenType = Bino::ScreenGeometry;
float ar;
float ar2[2];
if (2 == std::sscanf(qPrintable(paramList[0]), "%f:%f", ar2 + 0, ar2 + 1)) {
Expand Down Expand Up @@ -633,7 +641,7 @@ int main(int argc, char* argv[])
QSurfaceFormat::setDefaultFormat(format);

// Initialize Bino (in VR mode: only from the main process!)
Bino bino(screen, parser.isSet("swap-eyes"));
Bino bino(screenType, screen, parser.isSet("swap-eyes"));
if (guiMode || !vrChildProcess) {
bino.initializeOutput(audioOutputDeviceIndex >= 0
? audioOutputDevices[audioOutputDeviceIndex]
Expand Down
11 changes: 7 additions & 4 deletions src/qvrapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Copyright (C) 2016, 2017, 2018, 2019, 2020, 2021, 2022
* Computer Graphics Group, University of Siegen
* Written by Martin Lambers <[email protected]>
* Copyright (C) 2022, 2023
* 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 @@ -120,8 +120,8 @@ bool BinoQVRApp::initProcess(QVRProcess*)
QString vrdeviceVS = readFile(":src/shader-vrdevice.vert.glsl");
QString vrdeviceFS = readFile(":src/shader-vrdevice.frag.glsl");
if (isGLES) {
vrdeviceVS.prepend("#version 320 es\n");
vrdeviceFS.prepend("#version 320 es\n"
vrdeviceVS.prepend("#version 310 es\n");
vrdeviceFS.prepend("#version 310 es\n"
"precision mediump float;\n");
} else {
vrdeviceVS.prepend("#version 330\n");
Expand Down Expand Up @@ -166,7 +166,10 @@ void BinoQVRApp::render(QVRWindow*, const QVRRenderContext& context, const unsig
int v = (context.eye(view) == QVR_Eye_Right ? 1 : 0);
int texWidth = context.textureSize(view).width();
int texHeight = context.textureSize(view).height();
Bino::instance()->render(projectionMatrix, orientationMatrix, viewMatrix, v, texWidth, texHeight, textures[view]);
Bino::instance()->render(
context.unitedScreenWallBottomLeft(), context.unitedScreenWallBottomRight(), context.unitedScreenWallTopLeft(),
context.intersectedScreenWallBottomLeft(), context.intersectedScreenWallBottomRight(), context.intersectedScreenWallTopLeft(),
projectionMatrix, orientationMatrix, viewMatrix, v, texWidth, texHeight, textures[view]);
// Render VR device models (optional)
glUseProgram(_prg.programId());
for (int i = 0; i < QVRManager::deviceCount(); i++) {
Expand Down
8 changes: 5 additions & 3 deletions src/widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,8 @@ void Widget::rebuildDisplayPrgIfNecessary(OutputMode outputMode)
QString fragmentShaderSource = readFile(":src/shader-display.frag.glsl");
fragmentShaderSource.replace("$OUTPUT_MODE", QString::number(int(outputMode)));
if (isGLES) {
vertexShaderSource.prepend("#version 320 es\n");
fragmentShaderSource.prepend("#version 320 es\n"
vertexShaderSource.prepend("#version 310 es\n");
fragmentShaderSource.prepend("#version 310 es\n"
"precision mediump float;\n");
} else {
vertexShaderSource.prepend("#version 330\n");
Expand Down Expand Up @@ -297,7 +297,9 @@ void Widget::paintGL()
(_surroundHorizontalAngleBase + _surroundHorizontalAngleCurrent), 0.0f);
orientationMatrix.rotate(orientation.inverted());
}
Bino::instance()->render(projectionMatrix, orientationMatrix, viewMatrix, v, viewWidth, viewHeight, _viewTex[v]);
Bino::instance()->render(
QVector3D(), QVector3D(), QVector3D(), QVector3D(), QVector3D(), QVector3D(),
projectionMatrix, orientationMatrix, viewMatrix, v, viewWidth, viewHeight, _viewTex[v]);
// generate mipmaps for the view texture
glBindTexture(GL_TEXTURE_2D, _viewTex[v]);
glGenerateMipmap(GL_TEXTURE_2D);
Expand Down

0 comments on commit ab256c8

Please sign in to comment.