Compare commits

...

2 Commits

Author SHA1 Message Date
Shaun Reed 802107fdd4 Assimp IOSystem for Qt Resource paths 2023-01-15 16:05:08 -05:00
Shaun Reed 55dd8e5c3c Test packaging
+ Update assimp to latest
2023-01-15 10:14:24 -05:00
27 changed files with 526 additions and 86178 deletions

View File

@ -13,11 +13,11 @@ jobs:
os: [ubuntu-latest, windows-latest, macos-latest] os: [ubuntu-latest, windows-latest, macos-latest]
include: include:
- os: ubuntu-latest - os: ubuntu-latest
cmake: -DCMAKE_PREFIX_PATH="/home/runner/work/qtk/Qt/6.3.1/gcc_64/" cmake: -DCMAKE_PREFIX_PATH="/home/runner/work/qtk/Qt/6.5.0/gcc_64/"
- os: windows-latest - os: windows-latest
cmake: -DCMAKE_PREFIX_PATH="D:/a/qtk/qtk/Qt/6.3.1/mingw81_64/" cmake: -DCMAKE_PREFIX_PATH="D:/a/qtk/qtk/Qt/6.5.0/mingw81_64/"
- os: macos-latest - os: macos-latest
cmake: -DCMAKE_PREFIX_PATH="/home/runner/work/qtk/Qt/6.3.1/gcc_64/" cmake: -DCMAKE_PREFIX_PATH="/home/runner/work/qtk/Qt/6.5.0/gcc_64/"
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
@ -26,19 +26,47 @@ jobs:
- name: Install Qt - name: Install Qt
uses: jurplel/install-qt-action@v2 uses: jurplel/install-qt-action@v2
with: with:
version: '6.3.1' version: '6.5.0'
- name: Chocolatey Action - name: Chocolatey Action
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
uses: crazy-max/ghaction-chocolatey@v2.0.0 uses: crazy-max/ghaction-chocolatey@v2
with: with:
args: install pkgconfiglite --checksum e87b5ea3c9142256af60f2d5b917aa63b571e6a0 --checksum-type sha1 args: install pkgconfiglite
- name: Build Qtk - name: Build Qtk
shell: bash shell: bash
run: | run: |
cmake -S . -B build/ ${{ matrix.cmake }} -DQTK_UPDATE_SUBMODULES=ON && cmake --build build/ \ cmake -B build/ ${{ matrix.cmake }} -DQTK_UPDATE_SUBMODULES=ON
--target qtk-main cmake --build build/
- name: Package Qtk
shell: bash
run: |
cmake --build build/ --target package
- name: Package Qtk Sources
if: matrix.os != 'macos-latest'
shell: bash
run: |
cmake --build build/ --target package_source
- uses: actions/upload-artifact@v3
with:
name: qtk-packages-${{ matrix.os }}
path: |
build/packages/
!build/packages/_CPack_Packages/*
- name: Install Qtk
shell: bash
run: |
cmake --install build/
- uses: actions/upload-artifact@v3
with:
name: qtk-${{ matrix.os }}
path: install/*
Build-Qtk-Assimp-Targets: Build-Qtk-Assimp-Targets:
strategy: strategy:
@ -47,9 +75,9 @@ jobs:
os: [ubuntu-latest, macos-latest] os: [ubuntu-latest, macos-latest]
include: include:
- os: ubuntu-latest - os: ubuntu-latest
cmake: -DCMAKE_PREFIX_PATH="/home/runner/work/qtk/Qt/6.3.1/gcc_64/" cmake: -DCMAKE_PREFIX_PATH="/home/runner/work/qtk/Qt/6.5.0/gcc_64/"
- os: macos-latest - os: macos-latest
cmake: -DCMAKE_PREFIX_PATH="/home/runner/work/qtk/Qt/6.3.1/gcc_64/" -DASSIMP_NEW_INTERFACE=ON cmake: -DCMAKE_PREFIX_PATH="/home/runner/work/qtk/Qt/6.5.0/gcc_64/" -DASSIMP_NEW_INTERFACE=ON
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
@ -58,7 +86,7 @@ jobs:
- name: Install Qt - name: Install Qt
uses: jurplel/install-qt-action@v2 uses: jurplel/install-qt-action@v2
with: with:
version: '6.3.1' version: '6.5.0'
- name: Install Assimp MacOS - name: Install Assimp MacOS
if: matrix.os == 'macos-latest' if: matrix.os == 'macos-latest'
@ -75,5 +103,49 @@ jobs:
- name: Build Qtk - name: Build Qtk
shell: bash shell: bash
run: | run: |
cmake -S . -B build/ ${{ matrix.cmake }} && cmake --build build/ \ cmake -B build/ ${{ matrix.cmake }} && cmake --build build/ --target qtk-main
--target qtk-main
# TODO: Enable with tag only when done testing
# Release-Qtk:
# needs: Build-Qtk
# if: "always()"
# strategy:
# fail-fast: false
# matrix:
# os: [ubuntu-latest, windows-latest, macos-latest]
# include:
# - os: ubuntu-latest
# cqt: CQtDeployer.deb
# url: https://github.com/QuasarApp/CQtDeployer/releases/download/v1.6.2277/CQtDeployer_1.6.2277.ecc6eed_Linux_x86_64.deb
# qmake: /home/runner/work/qtk/Qt/6.5.0/gcc_64/bin/qmake
# - os: windows-latest
# cqt: CQtDeployer.exe
# url: https://github.com/QuasarApp/CQtDeployer/releases/download/v1.6.2277/CQtDeployer_1.6.2277.ecc6eed_Windows_AMD64.exe
# qmake: D:/a/qtk/qtk/Qt/6.5.0/mingw81_64/bin/qmake
# - os: macos-latest
# cqt: CQtDeployer.run
# url: https://github.com/QuasarApp/CQtDeployer/releases/download/v1.6.2277/CQtDeployer_1.6.2277.ecc6eed_Linux_x86_64.run
# qmake: /home/runner/work/qtk/Qt/6.5.0/gcc_64/bin/qmake
# runs-on: ${{ matrix.os }}
#
# steps:
# - uses: actions/download-artifact@v3
# with:
# name: qtk-${{ matrix.os }}
#
# - name: Install Qt
# uses: jurplel/install-qt-action@v2
# with:
# version: '6.5.0'
#
# - name: Package Qtk
# shell: bash
# run: |
# wget -O ${{ matrix.cqt }} ${{ matrix.url }}
# apt install -y ./${{ matrix.cqt }}
# cqtdeployer -bin qtk-main -qmake ${{ matrix.qmake }}
#
# - uses: actions/upload-artifact@v3
# with:
# name: qtk-installer-${{ matrix.os }}
# path: DistributionKit/

View File

@ -55,7 +55,7 @@ option(
OFF OFF
) )
set(QT_DIR "$ENV{HOME}/Code/Clones/Qt/" CACHE PATH "Path to Qt6") set(QT_DIR "$ENV{HOME}/Qt/" CACHE PATH "Path to Qt6")
# Qt Designer will look in different locations if WIN / Unix. # Qt Designer will look in different locations if WIN / Unix.
# These paths are for using Qt Designer integrated within Qt Creator. # These paths are for using Qt Designer integrated within Qt Creator.
@ -70,7 +70,7 @@ else()
endif() endif()
# This should be set to your Qt6 installation directory. # This should be set to your Qt6 installation directory.
set(QT_INSTALL_DIR "${QT_DIR}/6.3.1/gcc_64/" CACHE PATH "Path to Qt6 install") set(QT_INSTALL_DIR "${QT_DIR}/6.5.0/gcc_64" CACHE PATH "Path to Qt6 install")
# Point CMAKE_PREFIX_PATH to Qt6 install directory # Point CMAKE_PREFIX_PATH to Qt6 install directory
# If Qtk is built within Qt Creator this is not required. # If Qtk is built within Qt Creator this is not required.
list(APPEND CMAKE_PREFIX_PATH "${QT_INSTALL_DIR}") list(APPEND CMAKE_PREFIX_PATH "${QT_INSTALL_DIR}")
@ -98,6 +98,7 @@ endforeach()
################################################################################ ################################################################################
# Find Qt # Find Qt
find_package(Qt6 COMPONENTS Core UiPlugin OpenGLWidgets) find_package(Qt6 COMPONENTS Core UiPlugin OpenGLWidgets)
qt_standard_project_setup()
if(NOT Qt6_FOUND) if(NOT Qt6_FOUND)
message( message(
SEND_ERROR "[Qtk] Error: Unable to find Qt6 at CMAKE_PREFIX_PATH: " SEND_ERROR "[Qtk] Error: Unable to find Qt6 at CMAKE_PREFIX_PATH: "
@ -113,6 +114,8 @@ endif()
# Find Assimp # Find Assimp
if(QTK_UPDATE_SUBMODULES) if(QTK_UPDATE_SUBMODULES)
message(STATUS "[Qtk] Updating submodules...") message(STATUS "[Qtk] Updating submodules...")
set(ASSIMP_BUILD_TESTS OFF)
set(ASSIMP_INSTALL OFF)
submodule_update("${CMAKE_CURRENT_SOURCE_DIR}/extern/assimp/assimp/") submodule_update("${CMAKE_CURRENT_SOURCE_DIR}/extern/assimp/assimp/")
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/extern/assimp/assimp/") add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/extern/assimp/assimp/")
else() else()
@ -127,37 +130,3 @@ endif()
# Qtk # Qtk
################################################################################ ################################################################################
add_subdirectory(src) add_subdirectory(src)
if(WIN32)
get_target_property(_qt6_qmake_location Qt6::qmake IMPORTED_LOCATION)
execute_process(
COMMAND "${_qt6_qmake_location}" -query QT_INSTALL_PREFIX
RESULT_VARIABLE return_code
OUTPUT_VARIABLE qt6_install_prefix
OUTPUT_STRIP_TRAILING_WHITESPACE
)
file(TO_NATIVE_PATH "${qt6_install_prefix}/bin" qt6_install_prefix)
if(TARGET Qt6::windeployqt)
add_custom_command(
TARGET qtk-main
POST_BUILD
COMMAND set PATH=%PATH%$<SEMICOLON>${qt6_install_prefix}
COMMAND Qt6::windeployqt --dir "${CMAKE_BINARY_DIR}/windeployqt" "$<TARGET_FILE_DIR:qtk-main>/$<TARGET_FILE_NAME:qtk-main>"
)
install(DIRECTORY "${CMAKE_BINARY_DIR}/windeployqt/" DESTINATION bin)
endif()
if(MSVC AND TARGET Qt6::qmake)
set(VSUSER_FILE "${CMAKE_CURRENT_BINARY_DIR}/qtk-main.vcxproj.user")
file(TO_NATIVE_PATH "${CMAKE_BINARY_DIR}/extern/assimp/assimp/bin" assimp_bin)
file(WRITE ${VSUSER_FILE} "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")
file(APPEND ${VSUSER_FILE} "<Project xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n")
file(APPEND ${VSUSER_FILE} " <PropertyGroup>\n")
file(APPEND ${VSUSER_FILE} " <LocalDebuggerEnvironment>Path=$(SolutionDir)\\lib\\$(Configuration);${qt6_install_prefix};${assimp_bin};$(Path)\n")
file(APPEND ${VSUSER_FILE} "$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>\n")
file(APPEND ${VSUSER_FILE} " <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>\n")
file(APPEND ${VSUSER_FILE} " </PropertyGroup>\n")
file(APPEND ${VSUSER_FILE} "</Project>\n")
endif()
endif()

View File

@ -19,6 +19,7 @@ Key features that are planned:
* Save / load for scene data. The current inheritance model is temporary. * Save / load for scene data. The current inheritance model is temporary.
* Basic text editor for quickly modifying shaders attached to objects. * Basic text editor for quickly modifying shaders attached to objects.
* Shader / object properties panel to modify related settings. * Shader / object properties panel to modify related settings.
* Reduce size of application resources and git references.
The Qtk desktop application provides a model loader using [Assimp](https://assimp.org/) within a Qt widget application. The Qtk desktop application provides a model loader using [Assimp](https://assimp.org/) within a Qt widget application.
@ -33,8 +34,8 @@ and see some examples in the `resources/models/` directory.
Qtk was developed and tested using CLion and [Qt Creator](https://github.com/qt-creator/qt-creator). Qtk was developed and tested using CLion and [Qt Creator](https://github.com/qt-creator/qt-creator).
Simply open the root `CMakeLists.txt` with either of these editors and configurations will be loaded. Simply open the root `CMakeLists.txt` with either of these editors and configurations will be loaded.
This project has been ported to Qt6, which is not yet available in Ubuntu apt repositories. This project has been ported to **Qt 6.5.0**, which is not yet available in Ubuntu apt repositories.
To run this project, you will *need* to install [Qt6 Open Source Binaries](https://www.qt.io/download-qt-installer) for your system. To run this project, you will *need* to install [Qt6 Open Source Binaries](https://www.qt.io/download-qt-installer) for 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. 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.
#### Linux #### Linux
@ -101,6 +102,13 @@ If you see a small triangle floating by a model it represents the light source
that is being used for the shader rendering the model. These appear on models that is being used for the shader rendering the model. These appear on models
using phong, specular, and diffuse lighting techniques. using phong, specular, and diffuse lighting techniques.
Object names can be double-clicked in the tree view panel for quick camera
navigation. All panels and toolbars are dockable widgets that can be popped out
and reorganized as needed. Panels can be stacked to create a docked widget with
tabs. The central widget that provides the camera view into the scene cannot be
detached from the main window in this way. See the `View` menu to enable debug
console widgets for open scenes or reopen previously closed panels.
![](resources/screenshot.png) ![](resources/screenshot.png)
Spartan with no normals - Spartan with no normals -

@ -1 +1 @@
Subproject commit bd64cc88dff17f118ecf32ebcbacaf566f6b6449 Subproject commit eb328ce69dd7b06977aed125e967a41e835b8431

View File

@ -1,5 +1,5 @@
# Created by RapidCompact v4.3.2 | www.rapidcompact.com # Created by RapidCompact v4.3.2 | www.rapidcompact.com
mtllib rapid.mtl mtllib bird.mtl
o mesh_0 o mesh_0
v 290.631131412626928068 748.484123578408002686 -224.342122210487644907 v 290.631131412626928068 748.484123578408002686 -224.342122210487644907
v 282.356783853739386814 751.945844816198814442 -222.136356657249308455 v 282.356783853739386814 751.945844816198814442 -222.136356657249308455

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 254 KiB

View File

@ -1,16 +0,0 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl Lion
Ns 500.000001
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.800000 0.800000 0.800000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Bump normal.jpg
map_Kd diffuse.jpg
map_Ns roughness.jpg
refl specular.jpg

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 484 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 562 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

View File

@ -52,4 +52,79 @@
<file alias="skybox.frag">skybox/skybox.frag</file> <file alias="skybox.frag">skybox/skybox.frag</file>
<file alias="skybox.vert">skybox/skybox.vert</file> <file alias="skybox.vert">skybox/skybox.vert</file>
</qresource> </qresource>
<qresource prefix="/models">
<file>models/spartan/spartan.obj</file>
<file>models/alien-hominid/alien.obj</file>
<file>models/spartan/spartan.mtl</file>
<file>models/spartan/Spartan_Ears_Mat_BaseColor.png</file>
<file>models/spartan/Spartan_Undersuit_Mat_Specular.png</file>
<file>models/spartan/Spartan_Undersuit_Mat_Roughness.png</file>
<file>models/spartan/Spartan_Undersuit_Mat_Normal.png</file>
<file>models/spartan/Spartan_Undersuit_Mat_Metallic.png</file>
<file>models/spartan/Spartan_Undersuit_Mat_BaseColor.png</file>
<file>models/spartan/Spartan_Undersuit_Mat_AO.png</file>
<file>models/spartan/Spartan_Shoulder_Mat_Specular.png</file>
<file>models/spartan/Spartan_Shoulder_Mat_Roughness.png</file>
<file>models/spartan/Spartan_Shoulder_Mat_Normal.png</file>
<file>models/spartan/Spartan_Shoulder_Mat_Metallic.png</file>
<file>models/spartan/Spartan_Shoulder_Mat_BaseColor.png</file>
<file>models/spartan/Spartan_Shoulder_Mat_AO.png</file>
<file>models/spartan/Spartan_Legs_Mat_Specular.png</file>
<file>models/spartan/Spartan_Legs_Mat_Roughness.png</file>
<file>models/spartan/Spartan_Legs_Mat_Normal.png</file>
<file>models/spartan/Spartan_Legs_Mat_Metallic.png</file>
<file>models/spartan/Spartan_Legs_Mat_BaseColor.png</file>
<file>models/spartan/Spartan_Legs_Mat_AO.png</file>
<file>models/spartan/Spartan_Helmet_Mat_Specular.png</file>
<file>models/spartan/Spartan_Helmet_Mat_Roughness.png</file>
<file>models/spartan/Spartan_Helmet_Mat_Normal.png</file>
<file>models/spartan/Spartan_Helmet_Mat_Metallic.png</file>
<file>models/spartan/Spartan_Helmet_Mat_BaseColor.png</file>
<file>models/spartan/Spartan_Helmet_Mat_AO.png</file>
<file>models/spartan/Spartan_Ears_Mat_Specular.png</file>
<file>models/spartan/Spartan_Ears_Mat_Roughness.png</file>
<file>models/spartan/Spartan_Ears_Mat_Normal.png</file>
<file>models/spartan/Spartan_Ears_Mat_Metallic.png</file>
<file>models/spartan/Spartan_Ears_Mat_AO.png</file>
<file>models/spartan/Spartan_Chest_Mat_Specular.png</file>
<file>models/spartan/Spartan_Chest_Mat_Roughness.png</file>
<file>models/spartan/Spartan_Chest_Mat_Normal.png</file>
<file>models/spartan/Spartan_Chest_Mat_Metallic.png</file>
<file>models/spartan/Spartan_Chest_Mat_BaseColor.png</file>
<file>models/spartan/Spartan_Chest_Mat_AO.png</file>
<file>models/spartan/Spartan_Arms_Mat_Specular.png</file>
<file>models/spartan/Spartan_Arms_Mat_Roughness.png</file>
<file>models/spartan/Spartan_Arms_Mat_Normal.png</file>
<file>models/spartan/Spartan_Arms_Mat_Metallic.png</file>
<file>models/spartan/Spartan_Arms_Mat_BaseColor.png</file>
<file>models/spartan/Spartan_Arms_Mat_AO.png</file>
<file>models/spartan/lambert1_Roughness.png</file>
<file>models/spartan/lambert1_Nrm.png</file>
<file>models/spartan/lambert1_Colour-Opacity.png</file>
<file>models/backpack/specular.jpg</file>
<file>models/backpack/roughness.jpg</file>
<file>models/backpack/diffuse.jpg</file>
<file>models/backpack/normal.png</file>
<file>models/backpack/backpack.obj</file>
<file>models/backpack/backpack.mtl</file>
<file>models/backpack/ao.jpg</file>
<file>models/alien-hominid/specular.png</file>
<file>models/alien-hominid/roughness.png</file>
<file>models/alien-hominid/normal.png</file>
<file>models/alien-hominid/diffuse.png</file>
<file>models/alien-hominid/blaster_specular.png</file>
<file>models/alien-hominid/blaster_roughness.png</file>
<file>models/alien-hominid/blaster_normal.png</file>
<file>models/alien-hominid/blaster_emissive.png</file>
<file>models/alien-hominid/blaster_diffuse.png</file>
<file>models/alien-hominid/alien.mtl</file>
<file>models/scythe/scythe.obj</file>
<file>models/scythe/scythe.mtl</file>
<file>models/scythe/diffuse.png</file>
<file>models/bird/occlusion.jpg</file>
<file>models/bird/normal.jpg</file>
<file>models/bird/diffuse.jpg</file>
<file>models/bird/bird.obj</file>
<file>models/bird/bird.mtl</file>
</qresource>
</RCC> </RCC>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 KiB

After

Width:  |  Height:  |  Size: 316 KiB

View File

@ -41,4 +41,11 @@ set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
set(CPACK_PACKAGE_VENDOR "Shaun Reed") set(CPACK_PACKAGE_VENDOR "Shaun Reed")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Qt OpenGL 3D graphics library.") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Qt OpenGL 3D graphics library.")
set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/shaunrd0/qtk") set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/shaunrd0/qtk")
set(CPACK_SOURCE_IGNORE_FILES build;install;\.git;\.github;\.idea)
set(CPACK_PACKAGE_DIRECTORY packages/)
if(WIN32)
set(CPACK_SOURCE_GENERATOR ZIP)
else()
set(CPACK_SOURCE_GENERATOR TGZ)
endif()
include(CPack) include(CPack)

View File

@ -11,13 +11,14 @@
# Create a library of widgets used to build Qtk GUI # Create a library of widgets used to build Qtk GUI
set( set(
QTK_PLUGIN_LIBRARY_SOURCES QTK_PLUGIN_LIBRARY_SOURCES
qtkwidget.cpp qtkwidget.h qtkwidget.cpp
debugconsole.cpp debugconsole.ui debugconsole.cpp debugconsole.ui
toolbox.cpp toolbox.ui toolbox.cpp toolbox.ui
treeview.cpp treeview.ui treeview.cpp treeview.ui
) )
set( set(
QTK_PLUGIN_LIBRARY_HEADERS QTK_PLUGIN_LIBRARY_HEADERS
qtkwidget.h
debugconsole.h debugconsole.h
toolbox.h toolbox.h
treeview.h treeview.h
@ -50,16 +51,16 @@ install(
# Qtk Widget Collection Plugin # Qtk Widget Collection Plugin
################################################################################ ################################################################################
# Create a Qt Designer plugin for a collection of widgets from our library. # Create a Qt Designer plugin for a collection of widgets from our library.
qt_add_plugin(qtk-collection) qt_add_plugin(qtk_collection STATIC)
target_sources( target_sources(
qtk-collection PRIVATE qtk_collection PRIVATE
widgetplugincollection.cpp widgetplugincollection.h widgetplugincollection.cpp widgetplugincollection.h
widgetplugin.cpp widgetplugin.h widgetplugin.cpp widgetplugin.h
) )
target_link_libraries(qtk-collection PUBLIC qtk-plugin-library) target_link_libraries(qtk_collection PUBLIC qtk-plugin-library)
install( install(
TARGETS qtk-collection TARGETS qtk_collection
RUNTIME DESTINATION "${QTK_PLUGIN_INSTALL_DIR}" RUNTIME DESTINATION "${QTK_PLUGIN_INSTALL_DIR}"
BUNDLE DESTINATION "${QTK_PLUGIN_INSTALL_DIR}" BUNDLE DESTINATION "${QTK_PLUGIN_INSTALL_DIR}"
LIBRARY DESTINATION "${QTK_PLUGIN_INSTALL_DIR}" LIBRARY DESTINATION "${QTK_PLUGIN_INSTALL_DIR}"
@ -72,13 +73,11 @@ install(
set( set(
QTK_APP_SOURCES QTK_APP_SOURCES
examplescene.cpp examplescene.h examplescene.cpp examplescene.h
qtkmainwindow.cpp qtkmainwindow.ui qtkmainwindow.cpp qtkmainwindow.h qtkmainwindow.ui
qtkmainwindow.h
main.cpp main.cpp
) )
# TODO: Qtk library should not depend on these resources. (qtkapi.h)
# Or should some resources be installed somewhere? qt6_add_big_resources(QTK_APP_SOURCES "${QTK_RESOURCES}/resources.qrc")
qt6_add_resources(QTK_APP_SOURCES "${QTK_RESOURCES}/resources.qrc")
configure_file( configure_file(
resources.h.in resources.h.in
"${CMAKE_CURRENT_BINARY_DIR}/resources.h" "${CMAKE_CURRENT_BINARY_DIR}/resources.h"
@ -102,3 +101,44 @@ install(
RUNTIME DESTINATION bin RUNTIME DESTINATION bin
LIBRARY DESTINATION bin/lib LIBRARY DESTINATION bin/lib
) )
qt_generate_deploy_app_script(
TARGET qtk-main
FILENAME_VARIABLE QTK_DEPLOY_SCRIPT
NO_UNSUPPORTED_PLATFORM_ERROR
)
install(SCRIPT ${QTK_DEPLOY_SCRIPT})
if(WIN32)
get_target_property(_qt6_qmake_location Qt6::qmake IMPORTED_LOCATION)
execute_process(
COMMAND "${_qt6_qmake_location}" -query QT_INSTALL_PREFIX
RESULT_VARIABLE return_code
OUTPUT_VARIABLE qt6_install_prefix
OUTPUT_STRIP_TRAILING_WHITESPACE
)
file(TO_NATIVE_PATH "${qt6_install_prefix}/bin" qt6_install_prefix)
if(TARGET Qt6::windeployqt)
add_custom_command(
TARGET qtk-main
POST_BUILD
COMMAND set PATH=%PATH%$<SEMICOLON>${qt6_install_prefix}
COMMAND Qt6::windeployqt --dir "${CMAKE_BINARY_DIR}/windeployqt" "$<TARGET_FILE_DIR:qtk-main>/$<TARGET_FILE_NAME:qtk-main>"
)
install(DIRECTORY "${CMAKE_BINARY_DIR}/windeployqt/" DESTINATION bin)
endif()
if(MSVC AND TARGET Qt6::qmake)
set(VSUSER_FILE "${CMAKE_CURRENT_BINARY_DIR}/qtk-main.vcxproj.user")
file(TO_NATIVE_PATH "${CMAKE_BINARY_DIR}/extern/assimp/assimp/bin" assimp_bin)
file(WRITE ${VSUSER_FILE} "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")
file(APPEND ${VSUSER_FILE} "<Project xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n")
file(APPEND ${VSUSER_FILE} " <PropertyGroup>\n")
file(APPEND ${VSUSER_FILE} " <LocalDebuggerEnvironment>Path=$(SolutionDir)\\lib\\$(Configuration);${qt6_install_prefix};${assimp_bin};$(Path)\n")
file(APPEND ${VSUSER_FILE} "$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>\n")
file(APPEND ${VSUSER_FILE} " <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>\n")
file(APPEND ${VSUSER_FILE} " </PropertyGroup>\n")
file(APPEND ${VSUSER_FILE} "</Project>\n")
endif()
endif()

View File

@ -41,7 +41,7 @@ void ExampleScene::init() {
myCube->setColor(RED); myCube->setColor(RED);
addObject(myCube); addObject(myCube);
auto mySpartan = new Model("My spartan", PATH("/models/spartan/spartan.obj")); auto mySpartan = new Model("My spartan", ":/models/models/spartan/spartan.obj");
mySpartan->getTransform().setTranslation(0.0f, 0.5f, 0.0f); mySpartan->getTransform().setTranslation(0.0f, 0.5f, 0.0f);
mySpartan->getTransform().setScale(0.5f); mySpartan->getTransform().setScale(0.5f);
addObject(mySpartan); addObject(mySpartan);
@ -79,35 +79,30 @@ void ExampleScene::init() {
// 3D Model loading // 3D Model loading
auto model = addObject( auto model = addObject(
new Qtk::Model("backpack", PATH("/models/backpack/backpack.obj"))); new Qtk::Model("backpack", ":/models/models/backpack/backpack.obj"));
auto test = PATH("/models/backpack/backpack.obj");
// Sometimes model textures need flipped in certain directions // Sometimes model textures need flipped in certain directions
model->flipTexture("diffuse.jpg", false, true); model->flipTexture("diffuse.jpg", false, true);
model->getTransform().setTranslation(0.0f, 0.0f, -10.0f); model->getTransform().setTranslation(0.0f, 0.0f, -10.0f);
model = addObject(new Qtk::Model("bird", PATH("/models/bird/bird.obj"))); model = addObject(new Qtk::Model("bird", ":/models/models/bird/bird.obj"));
model->getTransform().setTranslation(2.0f, 2.0f, -10.0f); model->getTransform().setTranslation(2.0f, 2.0f, -10.0f);
// Sometimes the models are very large // Sometimes the models are very large
model->getTransform().scale(0.0025f); model->getTransform().scale(0.0025f);
model->getTransform().rotate(-110.0f, 0.0f, 1.0f, 0.0f); model->getTransform().rotate(-110.0f, 0.0f, 1.0f, 0.0f);
model = addObject(new Qtk::Model("lion", PATH("/models/lion/lion.obj")));
model->getTransform().setTranslation(-3.0f, -1.0f, -10.0f);
model->getTransform().scale(0.15f);
model = addObject( model = addObject(
new Qtk::Model("alien", PATH("/models/alien-hominid/alien.obj"))); new Qtk::Model("alien", ":/models/models/alien-hominid/alien.obj"));
model->getTransform().setTranslation(2.0f, -1.0f, -5.0f); model->getTransform().setTranslation(2.0f, -1.0f, -5.0f);
model->getTransform().scale(0.15f); model->getTransform().scale(0.15f);
model = model =
addObject(new Qtk::Model("scythe", PATH("/models/scythe/scythe.obj"))); addObject(new Qtk::Model("scythe", ":/models/models/scythe/scythe.obj"));
model->getTransform().setTranslation(-6.0f, 0.0f, -10.0f); model->getTransform().setTranslation(-6.0f, 0.0f, -10.0f);
model->getTransform().rotate(-90.0f, 1.0f, 0.0f, 0.0f); model->getTransform().rotate(-90.0f, 1.0f, 0.0f, 0.0f);
model->getTransform().rotate(90.0f, 0.0f, 1.0f, 0.0f); model->getTransform().rotate(90.0f, 0.0f, 1.0f, 0.0f);
model = addObject( model = addObject(
new Qtk::Model("masterChief", PATH("/models/spartan/spartan.obj"))); new Qtk::Model("masterChief", ":/models/models/spartan/spartan.obj"));
model->getTransform().setTranslation(-1.5f, 0.5f, -2.0f); model->getTransform().setTranslation(-1.5f, 0.5f, -2.0f);
@ -233,7 +228,7 @@ void ExampleScene::init() {
/* Test alien Model with phong lighting and specular mapping. */ /* Test alien Model with phong lighting and specular mapping. */
model = addObject(new Qtk::Model( model = addObject(new Qtk::Model(
"alienTest", PATH("/models/alien-hominid/alien.obj"), "alienTest", ":/models/models/alien-hominid/alien.obj",
":/shaders/model-specular.vert", ":/shaders/model-specular.frag")); ":/shaders/model-specular.vert", ":/shaders/model-specular.frag"));
model->getTransform().setTranslation(3.0f, -1.0f, 10.0f); model->getTransform().setTranslation(3.0f, -1.0f, 10.0f);
model->getTransform().scale(0.15f); model->getTransform().scale(0.15f);
@ -259,7 +254,7 @@ void ExampleScene::init() {
/* Test spartan Model with phong lighting, specular and normal mapping. */ /* Test spartan Model with phong lighting, specular and normal mapping. */
model = addObject(new Qtk::Model( model = addObject(new Qtk::Model(
"spartanTest", PATH("/models/spartan/spartan.obj"), "spartanTest", ":/models/models/spartan/spartan.obj",
":/shaders/model-normals.vert", ":/shaders/model-normals.frag")); ":/shaders/model-normals.vert", ":/shaders/model-normals.frag"));
model->getTransform().setTranslation(0.0f, -1.0f, 10.0f); model->getTransform().setTranslation(0.0f, -1.0f, 10.0f);
model->getTransform().scale(2.0f); model->getTransform().scale(2.0f);

View File

@ -6,8 +6,8 @@
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## ## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################*/ ##############################################################################*/
#include "examplescene.h"
#include "qtkmainwindow.h" #include "qtkmainwindow.h"
#include "examplescene.h"
#include "ui_qtkmainwindow.h" #include "ui_qtkmainwindow.h"
MainWindow * MainWindow::mainWindow_ = Q_NULLPTR; MainWindow * MainWindow::mainWindow_ = Q_NULLPTR;

View File

@ -1,8 +1,6 @@
#ifndef QTK_RESOURCES_H_IN_H #ifndef QTK_RESOURCES_H_IN_H
#define QTK_RESOURCES_H_IN_H #define QTK_RESOURCES_H_IN_H
#define RESOURCES "@CMAKE_SOURCE_DIR@/resources" // Not currently in use, but will be in the future.
#define PATH(a) RESOURCES a
#endif // QTK_RESOURCES_H_IN_H #endif // QTK_RESOURCES_H_IN_H

View File

@ -12,13 +12,15 @@ set(
QTK_LIBRARY_PUBLIC_HEADERS QTK_LIBRARY_PUBLIC_HEADERS
camera3d.h camera3d.h
input.h input.h
shape.h
meshrenderer.h meshrenderer.h
model.h model.h
modelmesh.h modelmesh.h
object.h object.h
qtkapi.h qtkapi.h
qtkiostream.h
qtkiosystem.h
scene.h scene.h
shape.h
skybox.h skybox.h
texture.h texture.h
transform3D.h transform3D.h
@ -28,18 +30,20 @@ set(
QTK_LIBRARY_SOURCES QTK_LIBRARY_SOURCES
camera3d.cpp camera3d.cpp
input.cpp input.cpp
shape.cpp
meshrenderer.cpp meshrenderer.cpp
model.cpp model.cpp
modelmesh.cpp modelmesh.cpp
object.cpp object.cpp
qtkiostream.cpp
qtkiosystem.cpp
scene.cpp scene.cpp
shape.cpp
skybox.cpp skybox.cpp
texture.cpp texture.cpp
transform3D.cpp transform3D.cpp
) )
qt6_add_resources(QTK_LIBRARY_SOURCES "${QTK_RESOURCES}/resources.qrc") qt6_add_big_resources(QTK_LIBRARY_SOURCES "${QTK_RESOURCES}/resources.qrc")
qt_add_library(qtk-library STATIC) qt_add_library(qtk-library STATIC)
target_sources(qtk-library PRIVATE ${QTK_LIBRARY_SOURCES}) target_sources(qtk-library PRIVATE ${QTK_LIBRARY_SOURCES})
target_sources( target_sources(

View File

@ -7,11 +7,10 @@
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## ## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################*/ ##############################################################################*/
#include <QFileInfo>
#include "model.h" #include "model.h"
#include "scene.h" #include "scene.h"
#include "texture.h" #include "texture.h"
#include "qtkiosystem.h"
using namespace Qtk; using namespace Qtk;
@ -65,27 +64,27 @@ Model * Qtk::Model::getInstance(const char * name) {
void Model::loadModel(const std::string & path) { void Model::loadModel(const std::string & path) {
Assimp::Importer import; Assimp::Importer import;
// If using a Qt Resource path, use QtkIOSystem for file handling.
// JIC a relative path was used, get the absolute file path if (path.front() == ':') {
QFileInfo info(path.c_str()); import.SetIOHandler(new QtkIOSystem());
info.makeAbsolute(); }
mDirectory = info.absoluteFilePath().toStdString(); // Used as base path for loading model textures.
mDirectory = path.substr(0, path.find_last_of('/'));
// Import the model, converting non-triangular geometry to triangles // Import the model, converting non-triangular geometry to triangles
// + And flipping texture UVs, etc.. // + And flipping texture UVs, etc..
// Assimp options: http://assimp.sourceforge.net/lib_html/postprocess_8h.html // Assimp options: http://assimp.sourceforge.net/lib_html/postprocess_8h.html
const aiScene * scene = import.ReadFile( const aiScene * scene = import.ReadFile(
mDirectory, aiProcess_Triangulate | aiProcess_FlipUVs path.c_str(), aiProcess_Triangulate | aiProcess_FlipUVs
| aiProcess_GenSmoothNormals | aiProcess_CalcTangentSpace | aiProcess_GenSmoothNormals
| aiProcess_OptimizeMeshes | aiProcess_SplitLargeMeshes); | aiProcess_CalcTangentSpace | aiProcess_OptimizeMeshes
| aiProcess_SplitLargeMeshes);
// If there were errors, print and return // If there were errors, print and return
if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) { if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) {
qDebug() << "Error::ASSIMP::" << import.GetErrorString() << "\n"; qDebug() << "Error::ASSIMP::" << import.GetErrorString() << "\n";
return; return;
} }
// If there were no errors, find the directory that contains this model
mDirectory = mDirectory.substr(0, mDirectory.find_last_of('/'));
// Pass the pointers to the root node and the scene to recursive function // Pass the pointers to the root node and the scene to recursive function
// + Base case breaks when no nodes left to process on model // + Base case breaks when no nodes left to process on model
@ -182,7 +181,6 @@ ModelMesh Model::processMesh(aiMesh * mesh, const aiScene * scene) {
if(mesh->mMaterialIndex >= 0) { if(mesh->mMaterialIndex >= 0) {
// Get the material attached to the model using Assimp // Get the material attached to the model using Assimp
aiMaterial * material = scene->mMaterials[mesh->mMaterialIndex]; aiMaterial * material = scene->mMaterials[mesh->mMaterialIndex];
// Get all diffuse textures from the material // Get all diffuse textures from the material
ModelMesh::Textures diffuseMaps = loadMaterialTextures( ModelMesh::Textures diffuseMaps = loadMaterialTextures(
material, aiTextureType_DIFFUSE, "texture_diffuse"); material, aiTextureType_DIFFUSE, "texture_diffuse");

View File

@ -27,7 +27,9 @@
* This cannot be defined within any namespace, but can be called by ctors. * This cannot be defined within any namespace, but can be called by ctors.
* See object.h for example. * See object.h for example.
*/ */
inline void initResources() { Q_INIT_RESOURCE(resources); } inline void initResources() {
Q_INIT_RESOURCE(resources);
}
namespace Qtk { namespace Qtk {
/** /**

82
src/qtk/qtkiostream.cpp Normal file
View File

@ -0,0 +1,82 @@
/*##############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2023 Shaun Reed, all rights reserved ##
## About: Custom IO stream for Qtk to support Qt Resource paths in Assimp ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################*/
#include "qtkiostream.h"
using namespace Qtk;
/*******************************************************************************
* Constructors, Destructors
******************************************************************************/
QtkIOStream::QtkIOStream(const char * pFile, const char * pMode) :
mFile(pFile) {
QString mode(pMode);
bool read = mode.contains('r');
bool write = mode.contains('w');
if(read && write) {
mFile.open(QIODevice::ReadWrite);
} else if(read) {
mFile.open(QIODevice::ReadOnly);
} else if(write) {
mFile.open(QIODevice::WriteOnly);
} else {
qDebug() << "[Qtk::QtkIOStream] Invalid file open mode: " << mode << "\n";
}
}
/*******************************************************************************
* Public Member Functions
******************************************************************************/
size_t QtkIOStream::Read(void * pvBuffer, size_t pSize, size_t pCount) {
size_t read = 0;
do {
auto readSize = mFile.read((char *)pvBuffer + read, pSize);
if(readSize < 0) {
qDebug() << "[Qtk::QtkIOStream] Failed to read (" << pSize
<< ") bytes from file at: " << mFile.filesystemFileName().c_str()
<< "\n";
return -1;
}
read += readSize;
} while(pCount--);
return read;
}
size_t QtkIOStream::Write(const void * pvBuffer, size_t pSize, size_t pCount) {
size_t wrote = 0;
do {
auto writeSize = mFile.write((char *)pvBuffer + wrote, pSize);
if(writeSize < 0) {
qDebug() << "[Qtk::QtkIOStream] Failed to write buffer with size ("
<< pSize
<< ") to file at: " << mFile.filesystemFileName().c_str()
<< "\n";
return -1;
}
wrote += writeSize;
} while(pCount--);
return wrote;
}
aiReturn QtkIOStream::Seek(size_t pOffset, aiOrigin pOrigin) {
return mFile.seek(pOffset) ? aiReturn_SUCCESS : aiReturn_FAILURE;
}
size_t QtkIOStream::Tell() const {
return mFile.pos();
}
size_t QtkIOStream::FileSize() const {
return mFile.size();
}
void QtkIOStream::Flush() {
mFile.flush();
}

85
src/qtk/qtkiostream.h Normal file
View File

@ -0,0 +1,85 @@
/*##############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2023 Shaun Reed, all rights reserved ##
## About: Custom IO stream for Qtk to support Qt Resource paths in Assimp ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################*/
#include <QFile>
#include <QFileInfo>
#include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp>
#ifndef QTK_QTKIOSTREAM_H
#define QTK_QTKIOSTREAM_H
namespace Qtk {
/**
* Custom Assimp IO stream to support QtkIOSystem file handling.
* Allows direct use of Qt Resource paths for loading models in Assimp.
*/
class QtkIOStream : public Assimp::IOStream {
friend class QtkIOSystem;
protected:
/** Constructor protected for private usage by QtkIOSystem */
QtkIOStream(const char * pFile, const char * pMode);
public:
~QtkIOStream() = default;
/**
* Reads data into pvBuffer in pCount batches of length pSize.
* The final pvBuffer will contain data read from all batches.
*
* @param pvBuffer Buffer to read data into.
* @param pSize Size in bytes for each read.
* @param pCount Number of reads to perform.
* @return Length of total bytes read into pvBuffer, or -1 on failure.
*/
size_t Read(void * pvBuffer, size_t pSize, size_t pCount) override;
/**
* Writes data from pvBuffer in pCount batches of length pSize.
* The final mFile member will contain all input data from pvBuffer.
*
* @param pvBuffer Buffer to write data from.
* @param pSize Size in bytes for each write.
* @param pCount Number of writes to perfom.
* @return Length of total bytes wrote into buffer, or -1 on failure.
*/
size_t Write(const void * pvBuffer, size_t pSize, size_t pCount) override;
/**
* Change the current read position in the mFile Qt resource.
*
* @param pOffset Offset position to set.
* @param pOrigin Origin position to use for relative offset.
* @return aiReturn_SUCCESS, or aiReturn_FAILURE on failure.
*/
aiReturn Seek(size_t pOffset, aiOrigin pOrigin) override;
/**
* @return The current position in mFile.
*/
[[nodiscard]] size_t Tell() const override;
/**
* @return The total size of mFile.
*/
[[nodiscard]] size_t FileSize() const override;
/**
* Flushes buffered data to mFile.
*/
void Flush() override;
private:
// Corresponding file for Qt Resource path.
QFile mFile;
};
} // namespace Qtk
#endif // QTK_QTKIOSTREAM_H

39
src/qtk/qtkiosystem.cpp Normal file
View File

@ -0,0 +1,39 @@
/*##############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2023 Shaun Reed, all rights reserved ##
## About: Custom IO system for Qtk to support Qt Resource paths in Assimp ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################*/
#include "qtkiosystem.h"
using namespace Qtk;
/*******************************************************************************
* Public Member Functions
******************************************************************************/
bool QtkIOSystem::Exists(const char * pFile) const {
return QFileInfo::exists(pFile);
}
char QtkIOSystem::getOsSeparator() const {
#ifndef _WIN32
return '/';
#else
return '\\';
#endif
}
Assimp::IOStream * QtkIOSystem::Open(const char * pFile, const char * pMode) {
if(!QFileInfo::exists(pFile)) {
qDebug() << "[Qtk::QtkIOSystem] failed to open file: " << pFile << "\n";
return nullptr;
}
return new QtkIOStream(pFile, pMode);
}
void QtkIOSystem::Close(Assimp::IOStream * pFile) {
delete pFile;
}

53
src/qtk/qtkiosystem.h Normal file
View File

@ -0,0 +1,53 @@
/*##############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2023 Shaun Reed, all rights reserved ##
## About: Custom IO system for Qtk to support Qt Resource paths in Assimp ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################*/
#include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp>
#include "qtkapi.h"
#include "qtkiostream.h"
#ifndef QTK_QTKIOSYSTEM_H
#define QTK_QTKIOSYSTEM_H
namespace Qtk {
/**
* Assimp IO system for loading models with assimp, using Qt Resource paths.
*/
class QtkIOSystem : public Assimp::IOSystem {
public:
QtkIOSystem() = default;
~QtkIOSystem() = default;
/**
* @param pFile File path to check.
* @return True if the file exists, else false.
*/
bool Exists(const char * pFile) const override;
/**
* @return Path separator for platform OS.
*/
[[nodiscard]] char getOsSeparator() const override;
/**
* @param pFile File to open for read / writing.
* @param pMode Mode to open file. See `man fopen`.
* @return QtkIOStream for the opened file.
*/
Assimp::IOStream * Open(
const char * pFile, const char * pMode = "rb") override;
/**
* @param pFile File to close.
*/
void Close(Assimp::IOStream * pFile) override;
};
} // namespace Qtk
#endif // QTK_QTKIOSYSTEM_H

View File

@ -19,8 +19,8 @@ QImage * OpenGLTextureFactory::initImage(
QImageReader::setAllocationLimit(512); QImageReader::setAllocationLimit(512);
auto loadedImage = new QImage(QImage(image).mirrored(flipX, flipY)); auto loadedImage = new QImage(QImage(image).mirrored(flipX, flipY));
if(loadedImage->isNull()) { if(loadedImage->isNull()) {
qDebug() << "Error loading image: " << image << "\n"; qDebug() << "[Qtk::OpenGLTextureFactory] Error loading image: " << image
qDebug() << QImageReader::supportedImageFormats(); << "\nSupported types: " << QImageReader::supportedImageFormats();
return Q_NULLPTR; return Q_NULLPTR;
} }