Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi-window support and backend refactor. #27

Merged
merged 30 commits into from
Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
4962838
Added base for vsgqtwindows example
robertosfield Jun 22, 2023
716530e
Added QMdiArea usage
robertosfield Jun 22, 2023
c64cf39
Reverted to using VukanSceneGraph for Vulkan instance/surface creation
robertosfield Jun 22, 2023
fc19825
Removed unneccessary line
robertosfield Jun 22, 2023
85f480b
ran clang-format
robertosfield Jun 22, 2023
3fe691c
Merge branch 'MultiWindows' into OldSchool
robertosfield Jun 22, 2023
e887eed
Removed unneccessary #define
robertosfield Jun 22, 2023
544d795
Added continuosUpdate toggle
robertosfield Jun 22, 2023
ca587db
Removed unused variable
robertosfield Jun 23, 2023
09481d9
Refactored ViewerWindow to support seperate initialization of Window …
robertosfield Jun 23, 2023
f7202ac
Added multiple window test code
robertosfield Jun 23, 2023
a7a974a
Further refinement of multi-window support
robertosfield Jun 26, 2023
04dad72
Implenmented MultiViewArea widget
robertosfield Jun 27, 2023
982b315
Fixed indentation
robertosfield Jun 27, 2023
5e3d62c
Replaced WindowTraits::surface member with WindowTraits::device.
robertosfield Jun 28, 2023
2d359c4
Updated to replace the WindowTraits::sharedWindow use the WindowTrait…
robertosfield Jun 28, 2023
3ba3892
build fix
robertosfield Jun 28, 2023
13b2415
Renamed original vsgqtwindows example to vsgqtmdi to better reflect t…
robertosfield Jun 28, 2023
223bac2
Removed unneccessary fallback
robertosfield Jun 29, 2023
974ce12
Renamed vsgQt::ViewerWindow to vsgQt::Window
robertosfield Jun 29, 2023
3dc2788
Completed renamed from vsgQt::ViewerWindow to vsgQt::Window
robertosfield Jun 29, 2023
6249d03
Added docs
robertosfield Jun 29, 2023
20cb24f
Added link to LICENSE
robertosfield Jun 29, 2023
eef1050
Improved naming
robertosfield Jun 29, 2023
0db5d5a
Bumped version to 0.1.0 in prep for release wrapping up multi-window …
robertosfield Jun 29, 2023
701fb06
Fixed typo
robertosfield Jun 29, 2023
01cf0c1
Added reference to VSG master
robertosfield Jun 29, 2023
1451e8e
Ran clang-format
robertosfield Jun 29, 2023
ab5ecab
Added better support for vsg::WindowTraits
robertosfield Jun 29, 2023
3b5ca8a
Added assingment of WindowTraits::x & y values
robertosfield Jun 29, 2023
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
8 changes: 4 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
cmake_minimum_required(VERSION 3.7)

project(vsgQt
VERSION 0.0.0
VERSION 0.1.0
DESCRIPTION "Qt integration with VulkanSceneGraph"
LANGUAGES CXX
)
set(VSGQT_SOVERSION 0)
set(VSGQT_RELEASE_CANDIDATE 0)
set(VSGQT_SOVERSION 1)
set(VSGQT_RELEASE_CANDIDATE 1)

set(VSGQT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "Root source directory of vsgQt")
set(VSGQT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}" CACHE INTERNAL "Root binary directory of vsgQt")
Expand All @@ -17,7 +17,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)

set(QT_PACKAGE_NAME Qt5 CACHE STRING "Set Qt package name, i.e. Qt5 or Qt6.")

find_package(vsg 1.0.0)
find_package(vsg 1.0.8)

vsg_setup_dir_vars()
vsg_setup_build_vars()
Expand Down
28 changes: 17 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,32 @@
# vsgQt
Open Source, cross platform C++ library providing integration of VulkanSceneGraph with Qt windowing. Supports Windows, Linux and macOS.
Open Source ([MIT Licensed](LICENSE.md)), cross platform C++ library providing integration of VulkanSceneGraph with Qt windowing. Supports Windows, Linux and macOS.

Qt, and hence vsgQt, is suited for interactive, event driven applications. For real-time applications we recommend that you use the VulkanSceneGraph's native windowing support and the standard VulkanSceneGraph frame driven shown in examples found in [vsgExamples](https://github.com/vsg-dev/vsgExamples/examples/viewer/vsgviewer/vsgviewer.cpp).
vsgQt provides full Vulkan support through the VulkanSceneGraph's built in Windows/vkSurface support rather than the limited Vulkan support that Qt-5.10 or later provide. Using the VulkanSceneGraph for providing Vulkan supports avoids the restriction that Qt's VulkanWindow has with not being able to share vkDevice between windows, and provides compatiblity with Qt versions prior to it adding Vulkan support. Sharing vsg::Device/vkDevice between Windows is crucial for providing multiple windows without blowing up GPU memory usage.

## Checking out vsgQt

git clone https://github.com/vsg-dev/vsgQt.git
~~~ sh
git clone https://github.com/vsg-dev/vsgQt.git
~~~

## Dependencies:

* [VulkanSDK](https://www.lunarg.com/vulkan-sdk/) version 1.2.162 or later
* [VulkanSceneGraph](https://github.com/vsg-dev/VulkanSceneGraph) master recommended.
* [VulkanSDK](https://www.lunarg.com/vulkan-sdk/) version 1.1.70 or later
* [VulkanSceneGraph](https://github.com/vsg-dev/VulkanSceneGraph) master, 1.0.8 or later.
* [CMake](https://cmake.org/) version 3.7 or later
* [Qt](https://www.qt.io/) version 5.10 or later
* [Qt](https://www.qt.io/) version 5 or later
* C++17 capable compiler

## Building vsgQt

cd vsgQt
cmake .
make -j 8
~~~ sh
cd vsgQt
cmake .
make -j 8
~~~

## Example
## Examples

* [vsgqtviewer](examples/vsgqtviewer/main.cpp) - example of QApplication/QMainWindow usage with vsgQt::ViewerWindow.
* [vsgqtviewer](examples/vsgqtviewer/main.cpp) - example of QApplication/QMainWindow usage with single vsgQt::Window.
* [vsgqtmdi](examples/vsgqtmdi/main.cpp) - example of QQMdiArea usage with multiple vsgQt::Window.
* [vsgqtwindows](examples/vsgqtwindows/main.cpp) - example of multiple vsgQt::Window.
2 changes: 2 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
add_subdirectory(vsgqtviewer)
add_subdirectory(vsgqtmdi)
add_subdirectory(vsgqtwindows)
19 changes: 19 additions & 0 deletions examples/vsgqtmdi/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
set(SOURCES
main.cpp
)

set(HEADERS
)

add_executable(vsgqtmdi ${MODE} ${SOURCES} ${HEADERS} ${FORMS})

target_link_libraries(vsgqtmdi vsgQt)

if (vsgXchange_FOUND)
target_compile_definitions(vsgqtmdi PRIVATE vsgXchange_FOUND)
target_link_libraries(vsgqtmdi vsgXchange::vsgXchange)
endif()


install(TARGETS vsgqtmdi DESTINATION bin)

178 changes: 178 additions & 0 deletions examples/vsgqtmdi/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
#include <vsg/all.h>

#ifdef vsgXchange_FOUND
# include <vsgXchange/all.h>
#endif

#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMdiArea>

#include <vsgQt/Window.h>
#include <iostream>

#include <iostream>

class MultiViewArea : public QMdiArea
{
public:

vsg::ref_ptr<vsg::WindowTraits> traits;
vsg::ref_ptr<vsg::Viewer> viewer;

MultiViewArea(QWidget *parent = nullptr) :
QMdiArea(parent),
viewer(vsg::Viewer::create())
{
viewer->addEventHandler(vsg::CloseHandler::create(viewer));
}

struct ViewWindow
{
vsgQt::Window* window = nullptr;
};

using Views = std::vector<ViewWindow>;
Views views;

size_t addView(vsg::ref_ptr<vsg::Node> vsg_scene, const QString& title = {})
{
auto window = new vsgQt::Window(viewer, traits);

auto widget = QWidget::createWindowContainer(window, this);
widget->setWindowTitle(title);

addSubWindow(widget);

if (views.empty()) widget->showMaximized();
else tileSubWindows();

window->initializeWindow();

// if first window to be created use it's device for future window creation.
if (!traits->device) traits->device = window->windowAdapter->getOrCreateDevice();

// compute the bounds of the scene graph to help position camera
vsg::ComputeBounds computeBounds;
vsg_scene->accept(computeBounds);
vsg::dvec3 centre = (computeBounds.bounds.min + computeBounds.bounds.max) * 0.5;
double radius = vsg::length(computeBounds.bounds.max - computeBounds.bounds.min) * 0.6;
double nearFarRatio = 0.001;

uint32_t width = window->traits->width;
uint32_t height = window->traits->height;

vsg::ref_ptr<vsg::EllipsoidModel> ellipsoidModel(vsg_scene->getObject<vsg::EllipsoidModel>("EllipsoidModel"));
vsg::ref_ptr<vsg::Camera> camera;
{
// set up the camera
auto lookAt = vsg::LookAt::create(centre + vsg::dvec3(0.0, -radius * 3.5, 0.0), centre, vsg::dvec3(0.0, 0.0, 1.0));

vsg::ref_ptr<vsg::ProjectionMatrix> perspective;
if (ellipsoidModel)
{
perspective = vsg::EllipsoidPerspective::create(
lookAt, ellipsoidModel, 30.0,
static_cast<double>(width) /
static_cast<double>(height),
nearFarRatio, false);
}
else
{
perspective = vsg::Perspective::create(
30.0,
static_cast<double>(width) /
static_cast<double>(height),
nearFarRatio * radius, radius * 4.5);
}

camera = vsg::Camera::create(perspective, lookAt, vsg::ViewportState::create(VkExtent2D{width, height}));
}

auto trackball = vsg::Trackball::create(camera, ellipsoidModel);
trackball->addWindow(*window);

viewer->addEventHandler(trackball);

auto commandGraph = vsg::createCommandGraphForView(*window, camera, vsg_scene);

viewer->addRecordAndSubmitTaskAndPresentation({commandGraph});
//viewer->assignRecordAndSubmitTaskAndPresentation({commandGraph});

views.push_back(ViewWindow{window});

return views.size()-1;
}
};

int main(int argc, char* argv[])
{
vsg::CommandLine arguments(&argc, argv);

// set up vsg::Options to pass in filepaths and ReaderWriter's and other IO
// realted options to use when reading and writing files.
auto options = vsg::Options::create();
options->fileCache = vsg::getEnv("VSG_FILE_CACHE");
options->paths = vsg::getEnvPaths("VSG_FILE_PATH");
#ifdef vsgXchange_FOUND
options->add(vsgXchange::all::create());
#endif

arguments.read(options);

auto windowTraits = vsg::WindowTraits::create();
windowTraits->windowTitle = "vsgQt viewer";
windowTraits->debugLayer = arguments.read({"--debug", "-d"});
windowTraits->apiDumpLayer = arguments.read({"--api", "-a"});
arguments.read("--samples", windowTraits->samples);
arguments.read({"--window", "-w"}, windowTraits->width, windowTraits->height);
if (arguments.read({"--fullscreen", "--fs"})) windowTraits->fullscreen = true;

if (arguments.errors())
return arguments.writeErrorMessages(std::cerr);

if (argc <= 1)
{
std::cout << "Please specify a 3d model or image file on the command line."
<< std::endl;
return 1;
}

vsg::Path filename = arguments[1];

auto vsg_scene = vsg::read_cast<vsg::Node>(filename, options);
if (!vsg_scene)
{
std::cout << "Failed to load a valid scenene graph, Please specify a 3d "
"model or image file on the command line."
<< std::endl;
return 1;
}

QApplication application(argc, argv);

QMainWindow* mainWindow = new QMainWindow();

auto mdiArea = new MultiViewArea(mainWindow);

mainWindow->setCentralWidget(mdiArea);

mdiArea->traits = windowTraits;

mdiArea->setContextMenuPolicy(Qt::PreventContextMenu);
mdiArea->setViewMode(QMdiArea::ViewMode::SubWindowView);
mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
mdiArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

mdiArea->addView(vsg_scene, "First Window");
mdiArea->addView(vsg_scene, "Second Window");
mdiArea->addView(vsg_scene, "Third Window");

mdiArea->viewer->compile();


mainWindow->show();

return application.exec();
}
37 changes: 16 additions & 21 deletions examples/vsgqtviewer/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,19 @@ int main(int argc, char* argv[])
auto options = vsg::Options::create();
options->fileCache = vsg::getEnv("VSG_FILE_CACHE");
options->paths = vsg::getEnvPaths("VSG_FILE_PATH");
#ifdef vsgXchange_FOUND
options->add(vsgXchange::all::create());
#endif

arguments.read(options);

auto windowTraits = vsg::WindowTraits::create();
windowTraits->windowTitle = "vsgQt viewer";
windowTraits->debugLayer = arguments.read({"--debug", "-d"});
windowTraits->apiDumpLayer = arguments.read({"--api", "-a"});
arguments.read("--samples", windowTraits->samples);
arguments.read({"--window", "-w"}, windowTraits->width, windowTraits->height);
if (arguments.read({"--fullscreen", "--fs"})) windowTraits->fullscreen = true;
if (arguments.read({"--window", "-w"}, windowTraits->width,windowTraits->height))
{
windowTraits->fullscreen = false;
}
auto horizonMountainHeight = arguments.value(0.0, "--hmh");

if (arguments.errors())
return arguments.writeErrorMessages(std::cerr);
Expand All @@ -60,21 +60,17 @@ int main(int argc, char* argv[])

QMainWindow* mainWindow = new QMainWindow();

auto* viewerWindow = new vsgQt::ViewerWindow();
auto* window = new vsgQt::Window(windowTraits);

viewerWindow->traits = windowTraits;
// provide the calls to set up the vsg::Viewer that will be used to render to the QWindow subclass vsgQt::Window
window->initializeCallback = [&](vsgQt::Window& vw, uint32_t width, uint32_t height) {

// provide the calls to set up the vsg::Viewer that will be used to render to the QWindow subclass vsgQt::ViewerWindow
viewerWindow->initializeCallback = [&](vsgQt::ViewerWindow& vw, uint32_t width, uint32_t height) {

auto& window = vw.windowAdapter;
if (!window) return false;
auto& vsg_window = vw.windowAdapter;
if (!vsg_window) return false;

auto& viewer = vw.viewer;
if (!viewer) viewer = vsg::Viewer::create();

viewer->addWindow(window);

// compute the bounds of the scene graph to help position camera
vsg::ComputeBounds computeBounds;
vsg_scene->accept(computeBounds);
Expand All @@ -91,9 +87,8 @@ int main(int argc, char* argv[])
{
perspective = vsg::EllipsoidPerspective::create(
lookAt, ellipsoidModel, 30.0,
static_cast<double>(width) /
static_cast<double>(height),
nearFarRatio, horizonMountainHeight);
static_cast<double>(width) / static_cast<double>(height),
nearFarRatio, 0.0);
}
else
{
Expand All @@ -104,15 +99,15 @@ int main(int argc, char* argv[])
nearFarRatio * radius, radius * 4.5);
}

auto camera = vsg::Camera::create(perspective, lookAt, vsg::ViewportState::create(window->extent2D()));
auto camera = vsg::Camera::create(perspective, lookAt, vsg::ViewportState::create(vsg_window->extent2D()));

// add close handler to respond the close window button and pressing escape
viewer->addEventHandler(vsg::CloseHandler::create(viewer));

// add trackball to enable mouse driven camera view control.
viewer->addEventHandler(vsg::Trackball::create(camera, ellipsoidModel));

auto commandGraph = vsg::createCommandGraphForView(window, camera, vsg_scene);
auto commandGraph = vsg::createCommandGraphForView(vsg_window, camera, vsg_scene);
viewer->assignRecordAndSubmitTaskAndPresentation({commandGraph});

viewer->compile();
Expand All @@ -121,7 +116,7 @@ int main(int argc, char* argv[])
};

// provide the calls to invokve the vsg::Viewer to render a frame.
viewerWindow->frameCallback = [](vsgQt::ViewerWindow& vw) {
window->frameCallback = [](vsgQt::Window& vw) {

if (!vw.viewer || !vw.viewer->advanceToNextFrame())
{
Expand All @@ -140,7 +135,7 @@ int main(int argc, char* argv[])
return true;
};

auto widget = QWidget::createWindowContainer(viewerWindow, mainWindow);
auto widget = QWidget::createWindowContainer(window, mainWindow);
mainWindow->setCentralWidget(widget);

mainWindow->resize(windowTraits->width, windowTraits->height);
Expand Down
19 changes: 19 additions & 0 deletions examples/vsgqtwindows/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
set(SOURCES
main.cpp
)

set(HEADERS
)

add_executable(vsgqtwindows ${MODE} ${SOURCES} ${HEADERS} ${FORMS})

target_link_libraries(vsgqtwindows vsgQt)

if (vsgXchange_FOUND)
target_compile_definitions(vsgqtwindows PRIVATE vsgXchange_FOUND)
target_link_libraries(vsgqtwindows vsgXchange::vsgXchange)
endif()


install(TARGETS vsgqtwindows DESTINATION bin)

Loading