From fc1ded833d2dba2802846da5af57c5b9ba9da593 Mon Sep 17 00:00:00 2001 From: Shaun Reed Date: Sat, 1 Apr 2023 12:43:30 -0400 Subject: [PATCH] WIP --- CMakeLists.txt | 23 ++- README.md | 128 +++++------- cmake/include/git_submodule.cmake | 2 +- cmake/templates/Config.cmake.in | 2 +- example-app/CMakeLists.txt | 36 +++- example-app/examplescene.cpp | 7 +- src/CMakeLists.txt | 34 ++-- src/app/CMakeLists.txt | 16 +- src/app/resources.h.in | 6 - src/qtk/CMakeLists.txt | 2 +- src/qtk/model.h | 317 +++++++++++++++--------------- 11 files changed, 286 insertions(+), 287 deletions(-) delete mode 100644 src/app/resources.h.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 57cc0a2..6c8cdb2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,14 +46,13 @@ include(GNUInstallDirs) # Options ################################################################################ option(QTK_DEBUG "Enable debugger" OFF) -option(QTK_UPDATE_SUBMODULES "Update external project (assimp) submodule" OFF) -option(QTK_BUILD_GUI "Build the Qtk desktop application" ON) -option(QTK_INSTALL_LIBRARY "Install libqtk to CMAKE_INSTALL_PREFIX path." ON) -option(QTK_INSTALL_PLUGINS "Install Qtk plugin collection to Qt Creator." OFF) -option(QTK_BUILD_EXAMPLE "Build the Qtk example desktop application" ON) -option(QTK_ENABLE_CCACHE "Enable ccache" ON) +option(QTK_SUBMODULES "Update external project (assimp) submodule" OFF) +option(QTK_GUI "Build the Qtk desktop application" ON) +option(QTK_PLUGINS "Install Qtk plugins to Qt Creator path." OFF) +option(QTK_EXAMPLE "Build the Qtk example desktop application" ON) +option(QTK_CCACHE "Enable ccache" ON) -if (QTK_ENABLE_CCACHE) +if (QTK_CCACHE) set(CMAKE_CXX_COMPILER_LAUNCHER ccache) endif() @@ -61,7 +60,7 @@ endif() option(QTK_PREFIX_QTCREATOR "Install Qtk to Qt Creator. Untested." OFF) # Option for bringing your own assimp installation; Otherwise not needed -# + If assimp is available system-wide we can just set QTK_UPDATE_SUBMODULES OFF +# + If assimp is available system-wide we can just set QTK_SUBMODULES OFF option( QTK_ASSIMP_NEW_INTERFACE "Use the assimp::assimp interface (WIN / OSX)" @@ -76,6 +75,10 @@ endif() # This should be set to your Qt6 installation directory. set(QT_INSTALL_DIR "$ENV{HOME}/Qt/6.5.0/gcc_64" CACHE PATH "Path to Qt6 install.") +set(Qt6_DIR "$ENV{HOME}/Qt/6.5.0/gcc_64/lib/") +if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install") +endif () # Point CMAKE_PREFIX_PATH to Qt6 install directory # If Qtk is built within Qt Creator this is not required. list(APPEND CMAKE_PREFIX_PATH "${QT_INSTALL_DIR}") @@ -134,7 +137,7 @@ if(NOT Qt6_FOUND) endif() # Find Assimp. -if(QTK_UPDATE_SUBMODULES) +if(QTK_SUBMODULES) # Required to statically link. add_compile_options(-fPIC) set(BUILD_SHARED_LIBS OFF CACHE STRING "Build static assimp libs" FORCE) @@ -166,7 +169,7 @@ endif() ################################################################################ add_subdirectory(src) -if(QTK_BUILD_EXAMPLE) +if(QTK_EXAMPLE) # Create a namespaced alias for linking with qtk_library in the example. add_library(${PROJECT_NAME}::qtk_library ALIAS qtk_library) add_subdirectory(example-app) diff --git a/README.md b/README.md index a1302b0..f7d5ffb 100644 --- a/README.md +++ b/README.md @@ -48,80 +48,51 @@ your system, **version 6.5.0** or later. Be sure to take note of the Qt6 installation directory, as we will need it to correctly set our `CMAKE_PREFIX_PATH` in the next steps. +If you are building on **Windows / Mac**, consider setting +the `-DASSIMP_NEW_INTERFACE` build flag. + If the build is configured with all options enabled, we can subsequently install individual components as needed with cmake. ```bash -cmake -B build-all/ -DQTK_BUILD_GUI=ON -DQTK_INSTALL_LIBRARY=ON -DQTK_INSTALL_PLUGINS=ON -``` +sudo apt update -y && sudo apt install libassimp-dev cmake build-essential git ccache libgl1-mesa-dev libglvnd-dev -y +git clone https://github.com/shaunrd0/qtk +cd qtk +# Configure the build with all components enabled +cmake -B build-all -DQTK_GUI=ON -DQTK_PLUGINS=ON -DQTK_EXAMPLE=ON -DCMAKE_PREFIX_PATH=$HOME/Qt/6.5.0/gcc_64 +# Build all targets +cmake --build build-all/ +```` + +By default, the build will not initialize Assimp as a git submodule and build +from source. +We can turn this on by setting the `-DQTK_SUBMODULES=ON` flag when running +CMake. +Building using this option will fetch and build Assimp for us, but builds will +take longer as a result. +Using `-DQTK_SUBMODULES=ON` supports providing assimp on cross-platform builds ( +Windows / Mac / Linux) and may be easier +to configure. ```bash -# Install libqtk only -cmake --install build-all/ --prefix=$(pwd)/install --component libqtk --- Install configuration: "Release" --- Up-to-date: /home/shaun/Code/qtk/install/lib/cmake/Qtk/QtkConfig.cmake --- Up-to-date: /home/shaun/Code/qtk/install/lib/cmake/Qtk/QtkConfigVersion.cmake --- Up-to-date: /home/shaun/Code/qtk/install/lib/cmake/Qtk/QtkTargets.cmake --- Up-to-date: /home/shaun/Code/qtk/install/lib/cmake/Qtk/QtkTargets-release.cmake --- Up-to-date: /home/shaun/Code/qtk/install/lib/static/libqtk_library.a --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/camera3d.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/input.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/meshrenderer.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/model.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/modelmesh.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/object.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/qtkapi.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/qtkiostream.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/qtkiosystem.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/scene.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/shape.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/skybox.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/texture.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/transform3D.h - -# Install Qtk widget collection to use Qt Designer -cmake --install build-all/ --prefix=$(pwd)/install --component collection --- Install configuration: "Release" --- Up-to-date: /home/shaun/Qt/6.5.0/gcc_64/../../Tools/QtCreator/lib/Qt/lib/libqtk_library.a --- Up-to-date: /home/shaun/Qt/6.5.0/gcc_64/../../Tools/QtCreator/lib/Qt/lib/libqtk_plugin_library.a --- Up-to-date: /home/shaun/Qt/6.5.0/gcc_64/../../Tools/QtCreator/lib/Qt/plugins/designer/libqtk_collection.so - -# Install Qtk desktop application (output removed) -cmake --install build-all/ --prefix=$(pwd)/install --component qtk +cmake -B build-all -DQTK_GUI=ON -DQTK_PLUGINS=ON -DQTK_EXAMPLE=ON -DQTK_SUBMODULES=ON -DCMAKE_PREFIX_PATH=$HOME/Qt/6.5.0/gcc_64 ``` #### Qtk GUI -Once Qt6 is installed, to build and run `qtk` on Ubuntu - - ```bash -sudo apt update -y && sudo apt install libassimp-dev cmake build-essential git ccache -y -git clone https://github.com/shaunrd0/qtk -cmake -S qtk/ -B qtk/build/ -DCMAKE_PREFIX_PATH=$HOME/Qt/6.5.0/gcc_64 -cmake --build qtk/build/ -j $(nproc --ignore=2) -./qtk/build/bin/qtk-main -``` - -By default, the build will not initialize Assimp as a git submodule and build -from source. -We can turn this on by setting the `-DQTK_UPDATE_SUBMODULES=ON` flag when -running CMake. -Building using this option will fetch and build Assimp for us, but builds will -take longer as a result. -Using `-DQTK_UPDATE_SUBMODULES=ON` supports providing assimp on cross-platform -builds (Windows / Mac / Linux) and may be easier to configure. - -```bash -cmake -S qtk/ -B qtk/build/ -DQTK_UPDATE_SUBMODULES=ON -DCMAKE_PREFIX_PATH=$HOME/Qt/6.5.0/gcc_64 -cmake --build qtk/build/ -j $(nproc --ignore=2) -./qtk/build/bin/qtk-main +cmake --build build-all/ --target qtk_gui -- -j $(nproc) +# Install Qtk desktop application (output removed) +# Installation prefix path must be absolute, since Qtk uses Qt deploy tools. +cmake --install build-all/ --component qtk_gui --prefix=$(pwd)/install +./install/bin/qtk_gui ``` If any errors are encountered loading plugins, we can debug plugin loading by setting the following environment variable - ```bash -QT_DEBUG_PLUGINS=1 ./qtk-main +QT_DEBUG_PLUGINS=1 ./install/bin/qtk_gui ``` #### Qtk Library @@ -131,12 +102,10 @@ We can install this library on a system path or a custom path and then set `CMAKE_PREFIX_PATH` to point to this location when building an application using libqtk. -Below is an example of installing on a system path. - ```bash -cmake -S qtk/ -B qtk/build/ -DCMAKE_PREFIX_PATH=$HOME/Qt/6.5.0/gcc_64 -DQTK_BUILD_GUI=OFF -DQTK_INSTALL_PLUGINS=OFF -DQTK_DEBUG=OFF -cmake --build qtk/build/ -j $(nproc --ignore=2) -sudo cmake --install . --prefix=/usr/local +# Install libqtk only +cmake --build build-all/ --target qtk_library -- -j $(nproc) +cmake --install build-all/ --component qtk_library --prefix=/usr/local -- Install configuration: "Release" -- Installing: /usr/local/lib/cmake/Qtk/QtkConfig.cmake -- Installing: /usr/local/lib/cmake/Qtk/QtkConfigVersion.cmake @@ -175,9 +144,14 @@ interfaces. To build and install the Qtk plugin collection - ```bash -cmake -S /path/to/qtk -B /path/to/qtk/build -DCMAKE_PREFIX_PATH=$HOME/Qt/6.5.0/gcc_64 -DQTK_INSTALL_PLUGINS=ON -DQTK_BUILD_GUI=OFF -DQTK_INSTALL_LIBRARY=OFF -cmake --build /path/to/qtk/build -cmake --install /path/to/qtk/build +cmake --build build-all/ --target qtk_plugins -- -j $(nproc) +# Install Qtk widget collection to use Qt Designer +# The path here should be initialized during build configuration, so no need for --prefix +cmake --install build-all/ --component qtk_plugins +-- Install configuration: "Release" +-- Up-to-date: /home/shaun/Qt/6.5.0/gcc_64/../../Tools/QtCreator/lib/Qt/lib/libqtk_library.a +-- Up-to-date: /home/shaun/Qt/6.5.0/gcc_64/../../Tools/QtCreator/lib/Qt/lib/libqtk_plugin_library.a +-- Up-to-date: /home/shaun/Qt/6.5.0/gcc_64/../../Tools/QtCreator/lib/Qt/plugins/designer/libqtk_collection.so ``` To uninstall after a previous installation, we can run the following command @@ -187,16 +161,22 @@ from the root of the repository. xargs rm < build/install_manifest.txt ``` -#### Windows / MacOS +#### Qtk Example -If you are building on **Windows / Mac**, consider setting -the `-DASSIMP_NEW_INTERFACE` build flag. +There is a simple example of using libqtk in the [example-app/](example-app) +directory. The example can be built standalone using `find_package` or as a +target within any qtk build. ```bash -cmake -S qtk/ -B qtk/build/ -DASSIMP_NEW_INTERFACE=ON -DCMAKE_PREFIX_PATH=$HOME/Qt/6.5.0/gcc_64;/path/to/assimp/ -cmake --build qtk/build/ -j $(nproc --ignore=2) +# Build the example from a configured qtk build tree +cmake --build build-all/ --target qtk_example -- -j $(nproc) +cmake --install build-all/ --component qtk_example --prefix=install +./install/bin/qtk_example ``` +See the README in the [example-app/](example-app) subdirectory for instructions +on standalone builds. + ### Controls You can fly around the scene if you hold the right mouse button and use WASD. @@ -253,7 +233,7 @@ CLion automatically. # Move to the root of the repo cd qtk # Build -cmake -B build && cmake --build build +cmake -B build && cmake --build build -- -j $(nproc) clang-tidy -p build/ --fix --config-file=.clang-tidy src/*.cpp src/*.h app/*.cpp app/*.h ``` @@ -320,12 +300,8 @@ Any of the above options can be appended with `--trace-expand` to debug package generation issues. The contents of all packages will depend on how the build was configured. -If we are generating packages for *only* libqtk, we -set `-DQTK_INSTALL_LIBRARY=ON` -during the cmake configuration step. To generate packages for Qtk desktop application, we should -set `-DQTK_BUILD_GUI=ON`, and optionally `-DQTK_INSTALL_LIBRARY=ON` if we would -like to bundle libqtk with the desktop application. +set `-DQTK_GUI=ON`. If this option is not set we will only package libqtk. The NSIS installer will allow component-specific path modification for all of these installation components through a GUI install application. diff --git a/cmake/include/git_submodule.cmake b/cmake/include/git_submodule.cmake index 26274e2..33f2f03 100644 --- a/cmake/include/git_submodule.cmake +++ b/cmake/include/git_submodule.cmake @@ -10,7 +10,7 @@ find_package(Git) # _PATH: Path to git submodule location that we want to update # + submodule_update(extern/assimp) function(submodule_update _PATH) - if (NOT QTK_UPDATE_SUBMODULES) + if (NOT QTK_SUBMODULES) return() endif() diff --git a/cmake/templates/Config.cmake.in b/cmake/templates/Config.cmake.in index 8026caa..d1383f2 100644 --- a/cmake/templates/Config.cmake.in +++ b/cmake/templates/Config.cmake.in @@ -2,7 +2,7 @@ include("${CMAKE_CURRENT_LIST_DIR}/QtkTargets.cmake") -set_and_check(QTK_EXECUTABLE "${PACKAGE_PREFIX_DIR}/bin/qtk_app") +set_and_check(QTK_EXECUTABLE "${PACKAGE_PREFIX_DIR}/bin/qtk_gui") set_and_check(QTK_INCLUDE_DIR "${PACKAGE_PREFIX_DIR}/include") set_and_check(QTK_LIBRARIES "${PACKAGE_PREFIX_DIR}/lib") diff --git a/example-app/CMakeLists.txt b/example-app/CMakeLists.txt index 673b8a3..acd7503 100644 --- a/example-app/CMakeLists.txt +++ b/example-app/CMakeLists.txt @@ -22,7 +22,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") endif() # If you did not install Qtk on a system path, point cmake to installation. -set(QTK_PATH /usr/local CACHE PATH "Path to installation of Qtk") +set(QTK_PATH ../build/install/lib/cmake/Qtk CACHE PATH "Path to installation of Qtk" FORCE) # If you did not install Qt6 on a system path, point cmake to installation. set(QT_INSTALL_DIR "$ENV{HOME}/Qt/6.5.0/gcc_64/" CACHE PATH "Path to Qt6") @@ -40,12 +40,6 @@ project( list(APPEND CMAKE_PREFIX_PATH "${QTK_PATH}") list(APPEND CMAKE_PREFIX_PATH "${QT_INSTALL_DIR}") -# Allow add_subdirectory on this project to use target ALIAS if available. -# If this example project is opened standalone we will use find_package. -if(NOT TARGET Qtk::qtk_library) - find_package(Qtk 0.2 REQUIRED) -endif() - # Print all QTK variables if (NOT Qtk_IS_TOP_LEVEL) get_cmake_property(VAR_NAMES VARIABLES) @@ -56,6 +50,12 @@ if (NOT Qtk_IS_TOP_LEVEL) endforeach() endif() +# Allow add_subdirectory on this project to use target ALIAS if available. +# If this example project is opened standalone we will use find_package. +if(NOT TARGET Qtk::qtk_library) + find_package(Qtk 0.2 REQUIRED) +endif() + find_package(Qt6 COMPONENTS Core Widgets OpenGLWidgets REQUIRED) set( @@ -65,6 +65,22 @@ set( examplewidget.cpp examplewidget.h ) -add_executable(example_app ${EXAMPLE_SOURCES}) -target_link_libraries(example_app PUBLIC Qt6::Widgets Qt6::OpenGLWidgets Qt6::Core) -target_link_libraries(example_app PUBLIC Qtk::qtk_library) +configure_file( + #[[INPUT]] "${CMAKE_CURRENT_SOURCE_DIR}/resources.h.in" + #[[OUTPUT]] "${CMAKE_CURRENT_BINARY_DIR}/resources.h" + @ONLY +) + +add_executable(qtk_example ${EXAMPLE_SOURCES}) +target_link_libraries(qtk_example PUBLIC Qt6::Widgets Qt6::OpenGLWidgets Qt6::Core) +target_link_libraries(qtk_example PUBLIC Qtk::qtk_library) +target_include_directories(qtk_example PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") + +install( + TARGETS qtk_example + COMPONENT qtk_example + BUNDLE DESTINATION . + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib/static + RUNTIME DESTINATION bin +) diff --git a/example-app/examplescene.cpp b/example-app/examplescene.cpp index 8e14f36..3243b6d 100644 --- a/example-app/examplescene.cpp +++ b/example-app/examplescene.cpp @@ -7,10 +7,11 @@ ##############################################################################*/ #include "examplescene.h" +#include using namespace Qtk; -ExampleScene::ExampleScene(Qtk::Scene * scene) : Qtk::SceneInterface(scene) { +ExampleScene::ExampleScene(Qtk::Scene *scene) : Qtk::SceneInterface(scene) { setSceneName("Example Scene"); getCamera().getTransform().setTranslation(-8.0f, 0.0f, 10.0f); getCamera().getTransform().setRotation(-5.0f, 0.0f, 1.0f, 0.0f); @@ -23,8 +24,10 @@ void ExampleScene::init() { setSkybox(skybox); auto spartan = new Model( - "spartan", "/home/kapper/Code/qtk/resources/models/spartan/spartan.obj"); + "spartan", std::string(QTK_EXAMPLE_SOURCE_DIR) + + "/../resources/models/spartan/spartan.obj"); addObject(spartan); + spartan->getTransform().setTranslation(-4.0f, 0.0f, 0.0f); auto mesh = addObject( new Qtk::MeshRenderer("rightTriangle", Triangle(QTK_DRAW_ARRAYS))); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 982c95f..e1c9459 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,14 +13,14 @@ install( FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" - COMPONENT libqtk + COMPONENT qtk_library DESTINATION lib/cmake/${PROJECT_NAME} ) install( EXPORT qtk_export FILE ${PROJECT_NAME}Targets.cmake NAMESPACE ${PROJECT_NAME}:: - COMPONENT libqtk + COMPONENT qtk_library DESTINATION lib/cmake/${PROJECT_NAME} ) # System install for qtk_library @@ -28,7 +28,7 @@ install( TARGETS qtk_library # Associate qtk_library target with qtk-export EXPORT qtk_export - COMPONENT libqtk + COMPONENT qtk_library FILE_SET HEADERS DESTINATION include INCLUDES DESTINATION include LIBRARY DESTINATION lib @@ -37,32 +37,32 @@ install( ) # Qtk Application -if(QTK_BUILD_GUI OR QTK_INSTALL_PLUGINS) +if(QTK_GUI OR QTK_PLUGINS) add_subdirectory(app) endif() -if(QTK_INSTALL_PLUGINS) +if(QTK_PLUGINS) # Optionally install custom Qtk plugins for Qt Designer. install( TARGETS qtk_library qtk_plugin_library - COMPONENT collection + COMPONENT qtk_plugins LIBRARY DESTINATION "${QTK_PLUGIN_LIBRARY_DIR}" ARCHIVE DESTINATION "${QTK_PLUGIN_LIBRARY_DIR}" RUNTIME DESTINATION "${QTK_PLUGIN_LIBRARY_DIR}" ) install( - TARGETS qtk_collection - COMPONENT collection + TARGETS qtk_plugins + COMPONENT qtk_plugins LIBRARY DESTINATION "${QTK_PLUGIN_INSTALL_DIR}" ARCHIVE DESTINATION "${QTK_PLUGIN_INSTALL_DIR}" RUNTIME DESTINATION "${QTK_PLUGIN_INSTALL_DIR}" ) endif() -if(QTK_BUILD_GUI) +if(QTK_GUI) install( - TARGETS qtk_app - COMPONENT qtk + TARGETS qtk_gui + COMPONENT qtk_gui BUNDLE DESTINATION . LIBRARY DESTINATION lib ARCHIVE DESTINATION lib/static @@ -70,11 +70,11 @@ if(QTK_BUILD_GUI) ) qt_generate_deploy_app_script( - TARGET qtk_app + TARGET qtk_gui OUTPUT_SCRIPT QTK_DEPLOY_SCRIPT NO_UNSUPPORTED_PLATFORM_ERROR ) - install(SCRIPT ${QTK_DEPLOY_SCRIPT} COMPONENT qtk) + install(SCRIPT ${QTK_DEPLOY_SCRIPT} COMPONENT qtk_gui) if(WIN32) if(MSVC AND TARGET Qt6::qmake) @@ -87,7 +87,7 @@ if(QTK_BUILD_GUI) ) file(TO_NATIVE_PATH "${QT6_INSTALL_PREFIX}/bin" QT6_INSTALL_PREFIX) - set(VSUSER_FILE "${CMAKE_CURRENT_BINARY_DIR}/qtk_app.vcxproj.user") + set(VSUSER_FILE "${CMAKE_CURRENT_BINARY_DIR}/qtk_gui.vcxproj.user") file(WRITE ${VSUSER_FILE} "\n") file(APPEND ${VSUSER_FILE} "\n") file(APPEND ${VSUSER_FILE} " \n") @@ -124,7 +124,7 @@ set(CPACK_THREADS 0) set(CPACK_PACKAGE_INSTALL_DIRECTORY "Qtk") # Remove any assimp components if defined by submodule. -if (QTK_UPDATE_SUBMODULES) +if (QTK_SUBMODULES) get_cmake_property(CPACK_COMPONENTS_ALL COMPONENTS) list(FILTER CPACK_COMPONENTS_ALL EXCLUDE REGEX .*assimp.*) list(REMOVE_ITEM CPACK_COMPONENTS_ALL Unspecified) @@ -136,7 +136,7 @@ set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON) # https://nsis.sourceforge.io/Reference/CreateShortCut set( CPACK_NSIS_CREATE_ICONS_EXTRA - "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Qtk.lnk' '$INSTDIR\\\\bin\\\\qtk_app.exe'" + "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Qtk.lnk' '$INSTDIR\\\\bin\\\\qtk_gui.exe'" ) set( CPACK_NSIS_DELETE_ICONS_EXTRA @@ -152,7 +152,7 @@ set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) # OSX set(CPACK_BUNDLE_NAME ${PROJECT_NAME}) -set(CPACK_BUNDLE_PLIST $/Info.plist) +set(CPACK_BUNDLE_PLIST $/Info.plist) set(CPACK_BUNDLE_ICON ${QTK_OSX_ICONS}) # Platform defaults for source bundles. diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index 6bbfcb6..5f85378 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -33,32 +33,32 @@ target_sources( target_link_libraries(qtk_plugin_library PUBLIC Qt6::UiPlugin qtk_library) ################################################################################ -# Qtk Widget Collection Plugin +# Qtk Widget Plugins ################################################################################ # Create a Qt Designer plugin for a collection of widgets from our library. -qt_add_plugin(qtk_collection SHARED) +qt_add_plugin(qtk_plugins SHARED) target_sources( - qtk_collection PRIVATE + qtk_plugins PRIVATE widgetplugincollection.cpp widgetplugincollection.h widgetplugin.cpp widgetplugin.h ) -target_link_libraries(qtk_collection PUBLIC qtk_plugin_library) +target_link_libraries(qtk_plugins PUBLIC qtk_plugin_library) ################################################################################ # Final Qtk Application ################################################################################ set( - QTK_APP_SOURCES + QTK_GUI_SOURCES qtkscene.cpp qtkscene.h main.cpp ) -qt_add_executable(qtk_app ${QTK_APP_SOURCES}) -target_link_libraries(qtk_app PRIVATE qtk_plugin_library) +qt_add_executable(qtk_gui ${QTK_GUI_SOURCES}) +target_link_libraries(qtk_gui PRIVATE qtk_plugin_library) set_target_properties( - qtk_app PROPERTIES + qtk_gui PROPERTIES WIN32_EXECUTABLE TRUE MACOSX_BUNDLE TRUE MACOSX_BUNDLE_BUNDLE_NAME Qtk diff --git a/src/app/resources.h.in b/src/app/resources.h.in deleted file mode 100644 index 31c7e81..0000000 --- a/src/app/resources.h.in +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef QTK_RESOURCES_H_IN_H -#define QTK_RESOURCES_H_IN_H - -// Not currently in use, but will be in the future. - -#endif // QTK_RESOURCES_H_IN_H diff --git a/src/qtk/CMakeLists.txt b/src/qtk/CMakeLists.txt index 42b9dcc..e67f83b 100644 --- a/src/qtk/CMakeLists.txt +++ b/src/qtk/CMakeLists.txt @@ -68,7 +68,7 @@ target_link_libraries( Qt6::Core Qt6::OpenGLWidgets Qt6::Widgets ) -if(QTK_UPDATE_SUBMODULES OR NOT ASSIMP_NEW_INTERFACE) +if(QTK_SUBMODULES OR NOT ASSIMP_NEW_INTERFACE) target_link_libraries(qtk_library PUBLIC assimp) elseif(ASSIMP_NEW_INTERFACE) target_link_libraries(qtk_library PUBLIC assimp::assimp) diff --git a/src/qtk/model.h b/src/qtk/model.h index 66f18c2..46d3b6d 100644 --- a/src/qtk/model.h +++ b/src/qtk/model.h @@ -27,177 +27,184 @@ namespace Qtk { * Top-level object that represents 3D models stored within a scene. */ class QTKAPI Model : public Object { - public: - /************************************************************************* - * Typedefs - ************************************************************************/ + public: + /************************************************************************* + * Typedefs + ************************************************************************/ - /** ModelManager typedef that will manage global model access. */ - typedef QHash ModelManager; + /** ModelManager typedef that will manage global model access. */ + typedef QHash ModelManager; - /************************************************************************* - * Constructors, Destructors - ************************************************************************/ + /************************************************************************* + * Constructors, Destructors + ************************************************************************/ - /** - * Constructs a Model - * If no shaders are provided we will use default shaders. - * - * @param name Name to use for the Model's objectName. - * @param path Path to the model to load for construction. - * @param vertexShader Optional path to custom vertex shader. - * @param fragmentShader Optional path to custom fragment shader. - */ - inline Model( - const char * name, const char * path, - const char * vertexShader = ":/shaders/model-basic.vert", - const char * fragmentShader = ":/shaders/model-basic.frag") : - Object(name, QTK_MODEL), - mModelPath(path), mVertexShader(vertexShader), - mFragmentShader(fragmentShader) { - loadModel(mModelPath); + /** + * Constructs a Model + * If no shaders are provided we will use default shaders. + * + * @param name Name to use for the Model's objectName. + * @param path Path to the model to load for construction. + * @param vertexShader Optional path to custom vertex shader. + * @param fragmentShader Optional path to custom fragment shader. + */ + inline Model( + const char *name, const char *path, + const char *vertexShader = ":/shaders/model-basic.vert", + const char *fragmentShader = ":/shaders/model-basic.frag") : + Object(name, QTK_MODEL), + mModelPath(path), mVertexShader(vertexShader), + mFragmentShader(fragmentShader) { + loadModel(mModelPath); + } + + inline Model( + std::string name, std::string path, + std::string vertexShader = ":/shaders/model-basic.vert", + std::string fragmentShader = ":/shaders/model-basic.frag") : + Model(name.c_str(), path.c_str(), vertexShader.c_str(), + fragmentShader.c_str()) {} + + inline ~Model() override { mManager.remove(getName().c_str()); } + + /************************************************************************* + * Public Methods + ************************************************************************/ + + /** + * Draws the model using attached shader program. + */ + void draw(); + + /** + * Draws the model using a custom shader program. + * + * @param shader Shader program to use to draw the model. + */ + void draw(QOpenGLShaderProgram &shader); + + /** + * Flip a texture associated with this model + * + * @param fileName The name of the texture to flip as it is stored on disk + * @param flipX Flip the texture along the X axis + * @param flipY Flip the texture along the Y axis + */ + void flipTexture( + const std::string &fileName, bool flipX = false, bool flipY = true); + + /************************************************************************* + * Setters + ************************************************************************/ + + /** + * Sets a uniform value for each ModelMesh within this Model. + * + * @tparam T The type of the value we are settings + * @param location The uniform location + * @param value The value to assign to the uniform + */ + template + inline void setUniform(const char *location, T value) { + for (auto &mesh: mMeshes) { + mesh.mProgram->bind(); + mesh.mProgram->setUniformValue(location, value); + mesh.mProgram->release(); } + } - inline ~Model() override { mManager.remove(getName().c_str()); } + /************************************************************************* + * Accessors + ************************************************************************/ - /************************************************************************* - * Public Methods - ************************************************************************/ + /** + * Accessor function for retrieving a ModelMesh globally. + * The mesh is retrieved from the mManager private member. + * + * @param name The name of the model to load as it was constructed. + * @return Pointer to the model stored within the scene. + */ + [[nodiscard]] static Model *getInstance(const char *name); - /** - * Draws the model using attached shader program. - */ - void draw(); + /** + * @return Transform3D attached to this Model. + */ + inline Transform3D &getTransform() { return mTransform; } - /** - * Draws the model using a custom shader program. - * - * @param shader Shader program to use to draw the model. - */ - void draw(QOpenGLShaderProgram & shader); + private: + /************************************************************************* + * Private Methods + ************************************************************************/ - /** - * Flip a texture associated with this model - * - * @param fileName The name of the texture to flip as it is stored on disk - * @param flipX Flip the texture along the X axis - * @param flipY Flip the texture along the Y axis - */ - void flipTexture( - const std::string & fileName, bool flipX = false, bool flipY = true); + /** + * Loads a model in .obj, .fbx, .gltf, and other formats. + * For a full list of formats see assimp documentation: + * https://github.com/assimp/assimp/blob/master/doc/Fileformats.md + * + * Large models should not be loaded into Qt resource system. + * Instead pass an *absolute* path to this function. + * Relative paths will break if Qtk is executed from different locations. + * + * @param path Absolute path to a model in .obj or another format accepted + * by assimp. + */ + void loadModel(const std::string &path); - /************************************************************************* - * Setters - ************************************************************************/ + /** + * Process a node in the model's geometry using Assimp. + * + * @param node The Assimp node to process. + * @param scene The Assimp scene for the loaded model. + */ + void processNode(aiNode *node, const aiScene *scene); - /** - * Sets a uniform value for each ModelMesh within this Model. - * - * @tparam T The type of the value we are settings - * @param location The uniform location - * @param value The value to assign to the uniform - */ - template - inline void setUniform(const char * location, T value) { - for(auto & mesh : mMeshes) { - mesh.mProgram->bind(); - mesh.mProgram->setUniformValue(location, value); - mesh.mProgram->release(); - } - } + /** + * Process a mesh within a node using Assimp. + * + * @param mesh The Assimp mesh to process. + * @param scene The Assimp scene for the loaded model. + * @return + */ + ModelMesh processMesh(aiMesh *mesh, const aiScene *scene); - /************************************************************************* - * Accessors - ************************************************************************/ + /** + * Load a collection of material texture using Assimp. + * This function loads diffuse, specular, and narmal material textures. + * A Mesh may have many of any or all of the texture types above. + * Models can have many Meshes attached. + * This function returns all textures for a single Mesh within a Model. + * + * @param mat Loaded Assimp material. + * @param type Type of the material. + * @param typeName Texture type name in string format. + * @return Collection of all textures for a single ModelMesh. + */ + ModelMesh::Textures loadMaterialTextures( + aiMaterial *mat, aiTextureType type, const std::string &typeName); - /** - * Accessor function for retrieving a ModelMesh globally. - * The mesh is retrieved from the mManager private member. - * - * @param name The name of the model to load as it was constructed. - * @return Pointer to the model stored within the scene. - */ - [[nodiscard]] static Model * getInstance(const char * name); + /** + * Sorts each mesh in the Model based on distance from the camera. + * This is for efficient drawing in OpenGL by preventing the drawing of + * objects not visible due to being partially or entirely behind another + * object. + */ + void sortModelMeshes(); - /** - * @return Transform3D attached to this Model. - */ - inline Transform3D & getTransform() { return mTransform; } + /************************************************************************* + * Private Members + ************************************************************************/ - private: - /************************************************************************* - * Private Methods - ************************************************************************/ + /** Static QHash used to store and access models globally. */ + static ModelManager mManager; - /** - * Loads a model in .obj, .fbx, .gltf, and other formats. - * For a full list of formats see assimp documentation: - * https://github.com/assimp/assimp/blob/master/doc/Fileformats.md - * - * Large models should not be loaded into Qt resource system. - * Instead pass an *absolute* path to this function. - * Relative paths will break if Qtk is executed from different locations. - * - * @param path Absolute path to a model in .obj or another format accepted - * by assimp. - */ - void loadModel(const std::string & path); - - /** - * Process a node in the model's geometry using Assimp. - * - * @param node The Assimp node to process. - * @param scene The Assimp scene for the loaded model. - */ - void processNode(aiNode * node, const aiScene * scene); - - /** - * Process a mesh within a node using Assimp. - * - * @param mesh The Assimp mesh to process. - * @param scene The Assimp scene for the loaded model. - * @return - */ - ModelMesh processMesh(aiMesh * mesh, const aiScene * scene); - - /** - * Load a collection of material texture using Assimp. - * This function loads diffuse, specular, and narmal material textures. - * A Mesh may have many of any or all of the texture types above. - * Models can have many Meshes attached. - * This function returns all textures for a single Mesh within a Model. - * - * @param mat Loaded Assimp material. - * @param type Type of the material. - * @param typeName Texture type name in string format. - * @return Collection of all textures for a single ModelMesh. - */ - ModelMesh::Textures loadMaterialTextures( - aiMaterial * mat, aiTextureType type, const std::string & typeName); - - /** - * Sorts each mesh in the Model based on distance from the camera. - * This is for efficient drawing in OpenGL by preventing the drawing of - * objects not visible due to being partially or entirely behind another - * object. - */ - void sortModelMeshes(); - - /************************************************************************* - * Private Members - ************************************************************************/ - - /** Static QHash used to store and access models globally. */ - static ModelManager mManager; - - /** Container to store N loaded textures for this model. */ - ModelMesh::Textures mTexturesLoaded {}; - /** Container to store N loaded meshes for this model. */ - std::vector mMeshes {}; - /** The directory this model and it's textures are stored. */ - std::string mDirectory {}; - /** File names for shaders and 3D model on disk. */ - std::string mVertexShader, mFragmentShader, mModelPath; + /** Container to store N loaded textures for this model. */ + ModelMesh::Textures mTexturesLoaded{}; + /** Container to store N loaded meshes for this model. */ + std::vector mMeshes{}; + /** The directory this model and it's textures are stored. */ + std::string mDirectory{}; + /** File names for shaders and 3D model on disk. */ + std::string mVertexShader, mFragmentShader, mModelPath; }; } // namespace Qtk