Compare commits

41 Commits

Author SHA1 Message Date
0ef62ebfa5 Add object details
+ Object and Shader detail panels
+ Connect model data to details panel
+ Ability to move and scale objects in GUI
+ View of shader code for selected object
2023-12-26 21:32:19 -05:00
2476d125f7 Fix drag and drop model loading 2023-04-29 10:02:40 -04:00
5118726cde Merge branch 'builds' into drag-and-drop 2023-04-14 14:50:10 -04:00
b3f9e3230e clean up 2023-04-09 21:44:27 -04:00
f5de113c9a Clean up cmake options 2023-04-09 20:41:02 -04:00
98793f7a75 ci
+ Windows failure fixed by
https://codereview.qt-project.org/c/qt/qtbase/+/468903
https://bugreports.qt.io/browse/QTBUG-112204
2023-04-09 18:21:32 -04:00
cd641072ab Don't build example on windows CI 2023-04-02 13:34:20 -04:00
460a44e7e6 Update CI 2023-04-02 13:15:46 -04:00
b0e123e6dd Format and more CI 2023-04-02 12:31:23 -04:00
be69d2d242 Add packaging for example app
+ Update CI workflows
2023-04-02 11:43:59 -04:00
3c2f7e8b5d CI 2023-04-01 13:56:43 -04:00
fc1ded833d WIP 2023-04-01 12:43:30 -04:00
5015c5c3a4 WIP drag and drop 2023-03-11 21:14:48 -05:00
2087f10681 README 2023-03-11 20:23:25 -05:00
e6b197d6fa Fix CI 2023-03-11 19:59:53 -05:00
6a52eee501 Debian packaging CI 2023-03-11 18:46:11 -05:00
6d51aef9cf Cleanup 2023-03-11 18:26:58 -05:00
5bde82d956 Format 2023-03-11 12:31:09 -05:00
ae5abb9939 Windows CI 2023-03-11 12:18:16 -05:00
d9c59a04ec Update CI for new targets 2023-03-11 11:30:17 -05:00
e6bcd131b7 Connect TreeWidget when scene is updated. 2023-03-11 11:21:26 -05:00
0659df94bd Add SceneInterface
+ Renames binaries qtk_main->qtk_app and example->example_app
2023-03-11 10:59:33 -05:00
0dcb6d337b CI 2023-02-11 10:01:52 -05:00
002bedd7ef Mac packaging 2023-02-05 10:21:38 -05:00
6ce71dda86 Update CI for new targets 2023-01-29 20:08:02 -05:00
b3484ced03 CI 2023-01-29 13:46:52 -05:00
5e886672da Packaging / install updates 2023-01-29 13:26:25 -05:00
126cd438e1 Cmake install components 2023-01-28 22:27:01 -05:00
39fa8e8cdc Fix windows packaging 2023-01-28 15:12:45 -05:00
48719412f2 CMake updates 2023-01-16 19:34:50 -05:00
aa32cbcc17 OSX packaging 2023-01-16 10:53:15 -05:00
cfefc49c53 CMake target renaming to avoid C++ errors with - 2023-01-15 17:04:06 -05:00
195a4ef30d Assimp IOSystem for Qt Resource paths 2023-01-15 16:06:15 -05:00
55dd8e5c3c Test packaging
+ Update assimp to latest
2023-01-15 10:14:24 -05:00
cf433ad7fc CMake packaging updates 2023-01-14 16:33:06 -05:00
4bc0ae22c6 Format 2023-01-02 22:19:38 -05:00
faa9fe28f7 CMake packaging 2023-01-02 22:18:53 -05:00
f83f68207d Add fontawesome icons
+ Clean up resource prefixes
2023-01-01 23:44:43 -05:00
85c9e2eac1 Clean and comment code 2023-01-01 22:51:46 -05:00
194888ed19 Refactor build system and UI
+ Install configs for Qt Designer plugins and Qtk application
+ Add Qtk plugin collection for Qt Designer
+ QtkWidget plugin
+ TreeView widget plugin
+ DebugConsole widget plugin
+ All widgets are fully integrated with Qt Designer
+ All widgets can be popped out or docked within the window
+ All widgets can be stacked to use tab view for side panels
+ All widgets can be toggled on/off through the view context menu
+ QtkWidget debug console
+ QtkWidget active scene TreeVew
+ QtkWidget dockable tool bar
+ Double-click an object name in the TreeView to focus camera
+ Separate libaray from widgets

There is still a lot to do here, but the major refactoring should be
done after this commit. Some of the new features were put together as
POC for working with the new UI. A few placeholder buttons were added
that have no functionality.
2023-01-01 22:49:04 -05:00
c948d9e1a6 Fix loading of QtkWidget in mainwindow 2022-12-11 12:36:07 -05:00
37 changed files with 343 additions and 597 deletions

View File

@@ -5,9 +5,6 @@ on:
pull_request: pull_request:
workflow_dispatch: workflow_dispatch:
env:
QT_VERSION: 6.6.0
jobs: jobs:
Qtk: Qtk:
env: env:
@@ -18,13 +15,13 @@ 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/$QT_VERSION/gcc_64/ $CONFIG cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ $CONFIG
flags: -j $(nproc) flags: -j $(nproc)
- os: windows-latest - os: windows-latest
cmake: -DCMAKE_PREFIX_PATH=D:/a/qtk/qtk/Qt/$QT_VERSION/mingw81_64/ $CONFIG cmake: -DCMAKE_PREFIX_PATH=D:/a/qtk/qtk/Qt/6.5.0/mingw81_64/ $CONFIG
flags: '' flags: ''
- os: macos-latest - os: macos-latest
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/ $CONFIG cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ $CONFIG
flags: -j $(nproc) flags: -j $(nproc)
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@@ -34,7 +31,7 @@ jobs:
- name: Install Qt - name: Install Qt
uses: jurplel/install-qt-action@v2 uses: jurplel/install-qt-action@v2
with: with:
version: ${{ env.QT_VERSION }} version: '6.5.0'
# Windows # Windows
@@ -148,13 +145,13 @@ 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/$QT_VERSION/gcc_64/ $CONFIG cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ $CONFIG
flags: -j $(nproc) flags: -j $(nproc)
- os: windows-latest - os: windows-latest
cmake: -DCMAKE_PREFIX_PATH=D:/a/qtk/qtk/Qt/$QT_VERSION/mingw81_64/ $CONFIG cmake: -DCMAKE_PREFIX_PATH=D:/a/qtk/qtk/Qt/6.5.0/mingw81_64/ $CONFIG
flags: '' flags: ''
- os: macos-latest - os: macos-latest
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/ $CONFIG cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ $CONFIG
flags: -j $(nproc) flags: -j $(nproc)
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@@ -164,7 +161,7 @@ jobs:
- name: Install Qt - name: Install Qt
uses: jurplel/install-qt-action@v2 uses: jurplel/install-qt-action@v2
with: with:
version: ${{ env.QT_VERSION }} version: '6.5.0'
# Windows # Windows
@@ -253,13 +250,13 @@ 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/$QT_VERSION/gcc_64/ $CONFIG cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ $CONFIG
flags: -j $(nproc) flags: -j $(nproc)
- os: windows-latest - os: windows-latest
cmake: -DCMAKE_PREFIX_PATH=D:/a/qtk/qtk/Qt/$QT_VERSION/mingw81_64/ $CONFIG cmake: -DCMAKE_PREFIX_PATH=D:/a/qtk/qtk/Qt/6.5.0/mingw81_64/ $CONFIG
flags: '' flags: ''
- os: macos-latest - os: macos-latest
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/ $CONFIG cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ $CONFIG
flags: -j $(nproc) flags: -j $(nproc)
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@@ -269,7 +266,7 @@ jobs:
- name: Install Qt - name: Install Qt
uses: jurplel/install-qt-action@v2 uses: jurplel/install-qt-action@v2
with: with:
version: ${{ env.QT_VERSION }} version: '6.5.0'
- name: Chocolatey Action - name: Chocolatey Action
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
@@ -298,9 +295,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/$QT_VERSION/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/$QT_VERSION/gcc_64/ 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:
@@ -309,7 +306,7 @@ jobs:
- name: Install Qt - name: Install Qt
uses: jurplel/install-qt-action@v2 uses: jurplel/install-qt-action@v2
with: with:
version: ${{ env.QT_VERSION }} version: '6.5.0'
- name: Install Assimp MacOS - name: Install Assimp MacOS
if: matrix.os == 'macos-latest' if: matrix.os == 'macos-latest'
@@ -325,7 +322,7 @@ jobs:
- name: Configure Qtk - name: Configure Qtk
shell: bash shell: bash
run: cmake -B build/ ${{ matrix.cmake }} -DQTK_CCACHE=OFF -DQTK_ASSIMP_NEW_INTERFACE=ON run: cmake -B build/ ${{ matrix.cmake }} -DQTK_CCACHE=OFF
- name: Build Qtk - name: Build Qtk
shell: bash shell: bash

View File

@@ -84,13 +84,17 @@ endif ()
set(QTK_RESOURCES "${CMAKE_SOURCE_DIR}/resources") set(QTK_RESOURCES "${CMAKE_SOURCE_DIR}/resources")
set(QTK_OSX_ICONS ${CMAKE_SOURCE_DIR}/resources/icons/osx/kilroy.icns) set(QTK_OSX_ICONS ${CMAKE_SOURCE_DIR}/resources/icons/osx/kilroy.icns)
# Print all QTK options and their values at the end of configuration.
get_cmake_property(VAR_NAMES VARIABLES)
list(FILTER VAR_NAMES INCLUDE REGEX "^Q[tT][kK]_.*$")
list(SORT VAR_NAMES)
################################################################################
# External Dependencies
################################################################################
# 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}")
if (QTK_PREFIX_QTCREATOR)
# TODO: This might be a bit strange and needs more testing.
set(CMAKE_INSTALL_PREFIX "${QT_INSTALL_DIR}")
endif()
set( set(
QT_CREATOR_DIR QT_CREATOR_DIR
@@ -98,11 +102,10 @@ set(
CACHE PATH "Qt Creator path used to install Qtk plugins for Qt Designer." CACHE PATH "Qt Creator path used to install Qtk plugins for Qt Designer."
) )
# Print all QTK options and their values at the end of configuration.
# We initialize this list here so that we can append to it as needed. # Print all QTK options and their values.
# All variables in this list will be printed at the end of configuration.
get_cmake_property(VAR_NAMES VARIABLES) get_cmake_property(VAR_NAMES VARIABLES)
list(FILTER VAR_NAMES INCLUDE REGEX "^[qQ][tT][kK]_.*$") list(FILTER VAR_NAMES INCLUDE REGEX "^Q[tT][kK]_.*$")
list(SORT VAR_NAMES) list(SORT VAR_NAMES)
################################################################################ ################################################################################
@@ -145,7 +148,6 @@ set(
CMAKE_PREFIX_PATH CMAKE_INSTALL_PREFIX QTK_PLUGIN_INSTALL_DIR QT6_INSTALL_PREFIX CMAKE_PREFIX_PATH CMAKE_INSTALL_PREFIX QTK_PLUGIN_INSTALL_DIR QT6_INSTALL_PREFIX
QT_INSTALL_DIR QT_INSTALL_DIR
) )
# Add QT6_INSTALL_PLUGINS to VAR_NAMES so it is printed at end of configuration.
list(APPEND VAR_NAMES QT6_INSTALL_PLUGINS) list(APPEND VAR_NAMES QT6_INSTALL_PLUGINS)
# Find Assimp. # Find Assimp.
@@ -187,8 +189,6 @@ if(QTK_EXAMPLE)
add_subdirectory(example-app EXCLUDE_FROM_ALL) add_subdirectory(example-app EXCLUDE_FROM_ALL)
endif() endif()
# Print all QTK options and their values at the end of configuration. This also
# prints any additional variables that we have added to VAR_NAMES and VAR_PATHS.
foreach(VAR_NAME IN LISTS VAR_NAMES VAR_PATHS) foreach(VAR_NAME IN LISTS VAR_NAMES VAR_PATHS)
if(VAR_NAME IN_LIST VAR_PATHS) if(VAR_NAME IN_LIST VAR_PATHS)
# Print absolute if variable is path # Print absolute if variable is path

View File

@@ -40,26 +40,26 @@ and [Qt Creator](https://github.com/qt-creator/qt-creator).
Simply open the root `CMakeLists.txt` with either of these editors and Simply open the root `CMakeLists.txt` with either of these editors and
configurations will be loaded. configurations will be loaded.
This project has been ported to **Qt 6.6.0**, which is not yet available in This project has been ported to **Qt 6.5.0**, which is not yet available in
Ubuntu apt repositories. Ubuntu apt repositories.
To run this project, you will *need* to To run this project, you will *need* to
install [Qt6 Open Source Binaries](https://www.qt.io/download-qt-installer) for install [Qt6 Open Source Binaries](https://www.qt.io/download-qt-installer) for
your system, **version 6.6.0** or later. your system, **version 6.5.0** or later.
Be sure to take note of the Qt6 installation directory, as we will need it to 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. correctly set our `CMAKE_PREFIX_PATH` in the next steps.
If you are building on **Windows / Mac**, consider setting If you are building on **Windows / Mac**, consider setting
the `-DQTK_ASSIMP_NEW_INTERFACE` cmake build option. the `-DASSIMP_NEW_INTERFACE` build flag.
If the build is configured with all options enabled, we can subsequently install If the build is configured with all options enabled, we can subsequently install
individual components as needed with cmake. individual components as needed with cmake.
```bash ```bash
sudo apt update -y && sudo apt install libassimp-dev cmake build-essential git ccache libgl1-mesa-dev libglvnd-dev zlib1g-dev -y 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 git clone https://github.com/shaunrd0/qtk
cd qtk cd qtk
# Configure the build with all components enabled # 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.6.0/gcc_64 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 # Build all targets
cmake --build build-all/ cmake --build build-all/
```` ````
@@ -75,7 +75,7 @@ Windows / Mac / Linux) and may be easier
to configure. to configure.
```bash ```bash
cmake -B build-all -DQTK_GUI=ON -DQTK_PLUGINS=ON -DQTK_EXAMPLE=ON -DQTK_SUBMODULES=ON -DCMAKE_PREFIX_PATH=$HOME/Qt/6.6.0/gcc_64 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 #### Qtk GUI
@@ -149,9 +149,9 @@ cmake --build build-all/ --target qtk_plugins -- -j $(nproc)
# The path here should be initialized during build configuration, so no need for --prefix # The path here should be initialized during build configuration, so no need for --prefix
cmake --install build-all/ --component qtk_plugins cmake --install build-all/ --component qtk_plugins
-- Install configuration: "Release" -- Install configuration: "Release"
-- Up-to-date: /home/shaun/Qt/6.6.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_library.a
-- Up-to-date: /home/shaun/Qt/6.6.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/lib/libqtk_plugin_library.a
-- Up-to-date: /home/shaun/Qt/6.6.0/gcc_64/../../Tools/QtCreator/lib/Qt/plugins/designer/libqtk_collection.so -- 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 To uninstall after a previous installation, we can run the following command

View File

@@ -13,8 +13,8 @@ using namespace Qtk;
ExampleScene::ExampleScene(Qtk::Scene * scene) : Qtk::SceneInterface(scene) { ExampleScene::ExampleScene(Qtk::Scene * scene) : Qtk::SceneInterface(scene) {
setSceneName("Example Scene"); setSceneName("Example Scene");
getCamera().setTranslation({-8.0f, 0.0f, 10.0f}); getCamera().getTransform().setTranslation(-8.0f, 0.0f, 10.0f);
getCamera().setRotation(0.0f, 1.0f, 0.0f, -5.0f); getCamera().getTransform().setRotation(-5.0f, 0.0f, 1.0f, 0.0f);
} }
ExampleScene::~ExampleScene() {} ExampleScene::~ExampleScene() {}
@@ -23,9 +23,9 @@ void ExampleScene::init() {
auto skybox = new Qtk::Skybox("Skybox"); auto skybox = new Qtk::Skybox("Skybox");
setSkybox(skybox); setSkybox(skybox);
std::string spartanPath = QTK_EXAMPLE_SOURCE_DIR; auto spartan = new Model(
spartanPath += "/resources/models/spartan/spartan.obj"; "spartan", std::string(QTK_EXAMPLE_SOURCE_DIR)
auto spartan = new Model("spartan", spartanPath.c_str()); + "/../resources/models/spartan/spartan.obj");
addObject(spartan); addObject(spartan);
spartan->getTransform().setTranslation(-4.0f, 0.0f, 0.0f); spartan->getTransform().setTranslation(-4.0f, 0.0f, 0.0f);
@@ -64,10 +64,10 @@ void ExampleScene::update() {
// Pitch forward and roll sideways // Pitch forward and roll sideways
MeshRenderer::getInstance("leftTriangle") MeshRenderer::getInstance("leftTriangle")
->getTransform() ->getTransform()
.rotate(1.0f, 0.0f, 0.0f, 0.75f); .rotate(0.75f, 1.0f, 0.0f, 0.0f);
MeshRenderer::getInstance("rightTriangle") MeshRenderer::getInstance("rightTriangle")
->getTransform() ->getTransform()
.rotate(0.0f, 0.0f, 1.0f, 0.75f); .rotate(0.75f, 0.0f, 0.0f, 1.0f);
static float translateX = 0.025f; static float translateX = 0.025f;
float limit = -9.0f; // Origin position.x - 2.0f float limit = -9.0f; // Origin position.x - 2.0f
@@ -86,12 +86,12 @@ void ExampleScene::update() {
.translate(-translateX, 0.0f, 0.0f); .translate(-translateX, 0.0f, 0.0f);
MeshRenderer::getInstance("topTriangle") MeshRenderer::getInstance("topTriangle")
->getTransform() ->getTransform()
.rotate(0.2f, 0.0f, 0.4f, 0.75f); .rotate(0.75f, 0.2f, 0.0f, 0.4f);
MeshRenderer::getInstance("bottomTriangle") MeshRenderer::getInstance("bottomTriangle")
->getTransform() ->getTransform()
.rotate(0.0f, 0.2f, 0.4f, 0.75f); .rotate(0.75f, 0.0f, 0.2f, 0.4f);
MeshRenderer::getInstance("centerCube") MeshRenderer::getInstance("centerCube")
->getTransform() ->getTransform()
.rotate(0.2f, 0.4f, 0.6f, 0.75f); .rotate(0.75f, 0.2f, 0.4f, 0.6f);
} }

View File

@@ -1,6 +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 QTK_EXAMPLE_SOURCE_DIR "@CMAKE_SOURCE_DIR@" #define QTK_EXAMPLE_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@"
#endif // QTK_RESOURCES_H_IN_H #endif // QTK_RESOURCES_H_IN_H

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 MiB

View File

@@ -1,6 +1,5 @@
<RCC> <RCC>
<qresource prefix="/textures"> <qresource prefix="/textures">
<file alias="plaster.png">images/plaster.png</file>
<file alias="crate.png">images/crate.png</file> <file alias="crate.png">images/crate.png</file>
<file alias="stone.png">images/stone.png</file> <file alias="stone.png">images/stone.png</file>
<file alias="wood.png">images/wood.png</file> <file alias="wood.png">images/wood.png</file>

View File

@@ -47,13 +47,13 @@ target_link_libraries(qtk_plugins PUBLIC qtk_plugin_library)
################################################################################ ################################################################################
# Final Qtk Application # Final Qtk Application
################################################################################ ################################################################################
# Source files for the main window and core application
set( set(
QTK_GUI_SOURCES QTK_GUI_SOURCES
qtkscene.cpp qtkscene.h qtkscene.cpp qtkscene.h
# logger.cpp logger.h
main.cpp main.cpp
) )
qt_add_executable(qtk_gui ${QTK_GUI_SOURCES}) qt_add_executable(qtk_gui ${QTK_GUI_SOURCES})
target_link_libraries(qtk_gui PRIVATE qtk_plugin_library) target_link_libraries(qtk_gui PRIVATE qtk_plugin_library)

View File

@@ -28,7 +28,6 @@ DebugConsole::DebugConsole(
auto qtkWidget = dynamic_cast<QtkWidget *>(owner); auto qtkWidget = dynamic_cast<QtkWidget *>(owner);
if(qtkWidget) { if(qtkWidget) {
connect( connect(qtkWidget, &QtkWidget::sendLog, this, &DebugConsole::sendLog);
qtkWidget->getLogger(), &Logger::sendLog, this, &DebugConsole::sendLog);
} }
} }

View File

@@ -61,8 +61,7 @@ namespace Qtk {
* @param context The DebugContext to use for the message. * @param context The DebugContext to use for the message.
* Default value is Status. * Default value is Status.
*/ */
inline void sendLog(QString message, Qtk::DebugContext context = Status) { inline void sendLog(QString message, DebugContext context = Status) {
// qDebug() << "[LOGGER]: " << qPrintable(message) << "; LOGGER";
mConsole->setTextColor(logColor(context)); mConsole->setTextColor(logColor(context));
mConsole->append(logPrefix(message, context)); mConsole->append(logPrefix(message, context));
} }

View File

@@ -1,107 +0,0 @@
/*##############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2023 Shaun Reed, all rights reserved ##
## About: Logger for Qtk ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################*/
#include "logger.h"
#include "qtkwidget.h"
using namespace Qtk;
Logger::Logger(Qtk::QtkWidget * parent) : QObject(parent) {
// connect(
// this, SIGNAL(sendLog(QString, Qtk::DebugContext)), this,
// SLOT(log(QString, Qtk::DebugContext)));
if(parent != Q_NULLPTR) {
connect(
parent, SIGNAL(sendLog(QString, Qtk::DebugContext)), this,
SLOT(log(QString, Qtk::DebugContext)));
}
}
std::pair<QString, DebugContext> Logger::log(const QOpenGLDebugMessage & msg) {
QString error_msg;
DebugContext context;
// Format based on severity
switch(msg.severity()) {
case QOpenGLDebugMessage::NotificationSeverity:
error_msg += "--";
context = Status;
break;
case QOpenGLDebugMessage::HighSeverity:
error_msg += "!!";
context = Fatal;
break;
case QOpenGLDebugMessage::MediumSeverity:
error_msg += "!~";
context = Error;
break;
case QOpenGLDebugMessage::LowSeverity:
error_msg += "~~";
context = Warn;
break;
case QOpenGLDebugMessage::InvalidSeverity:
error_msg += "??";
context = Invalid;
break;
case QOpenGLDebugMessage::AnySeverity:
error_msg += "**";
context = Any;
break;
}
error_msg += " (";
// Format based on source
#define CASE(c) \
case QOpenGLDebugMessage::c: \
error_msg += #c; \
break
switch(msg.source()) {
CASE(APISource);
CASE(WindowSystemSource);
CASE(ShaderCompilerSource);
CASE(ThirdPartySource);
CASE(ApplicationSource);
CASE(OtherSource);
CASE(InvalidSource);
CASE(AnySource);
}
#undef CASE
error_msg += " : ";
// Format based on type
#define CASE(c) \
case QOpenGLDebugMessage::c: \
error_msg += #c; \
break
switch(msg.type()) {
CASE(InvalidType);
CASE(ErrorType);
CASE(DeprecatedBehaviorType);
CASE(UndefinedBehaviorType);
CASE(PortabilityType);
CASE(PerformanceType);
CASE(OtherType);
CASE(MarkerType);
CASE(GroupPushType);
CASE(GroupPopType);
CASE(AnyType);
}
#undef CASE
error_msg += ")\n" + msg.message();
log(error_msg, context);
return {error_msg, context};
}
void Logger::log(const QString & message, DebugContext context) {
const QString log_msg = "[LOGGER]: " + message + "; LOGGER";
qDebug() << qPrintable(log_msg);
emit sendLog(log_msg, context);
}

View File

@@ -1,37 +0,0 @@
/*##############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2023 Shaun Reed, all rights reserved ##
## About: Logger for Qtk ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################*/
#ifndef QTK_LOGGER_H
#define QTK_LOGGER_H
#include <QOpenGLDebugMessage>
#include <QString>
#include "qtk/qtkapi.h"
namespace Qtk {
class QtkWidget;
class Logger : public QObject {
Q_OBJECT
public:
explicit Logger(Qtk::QtkWidget * parent = nullptr);
public slots:
std::pair<QString, DebugContext> log(
const QOpenGLDebugMessage & msg);
void log(
const QString & message,
Qtk::DebugContext context = Qtk::DebugContext::Status);
signals:
void sendLog(const QString & message, Qtk::DebugContext context);
};
} // namespace Qtk
#endif // QTK_LOGGER_H

View File

@@ -41,11 +41,6 @@ MainWindow::MainWindow(QWidget * parent) : QMainWindow(parent) {
&Qtk::ToolBox::updateFocus); &Qtk::ToolBox::updateFocus);
} }
// TODO: Fix / use MainWindow in Qt Designer to add these dock widgets.
// For now we will add them manually, but we should be able to do this in the
// designer. At the moment if you edit the UI in designer the dock widget
// areas below will override the designer settings.
// Dock the toolbox widget to the main window. // Dock the toolbox widget to the main window.
addDockWidget(Qt::LeftDockWidgetArea, ui_->qtk__ToolBox); addDockWidget(Qt::LeftDockWidgetArea, ui_->qtk__ToolBox);
// Add an option to toggle active widgets in the GUI's toolbar 'view' menu. // Add an option to toggle active widgets in the GUI's toolbar 'view' menu.
@@ -87,7 +82,7 @@ Qtk::QtkWidget * MainWindow::getQtkWidget(const QString & name) {
return views_[name]; return views_[name];
} }
void MainWindow::refreshScene(const QString & sceneName) { void MainWindow::refreshScene(QString sceneName) {
// TODO: Select TreeView using sceneName // TODO: Select TreeView using sceneName>
ui_->qtk__TreeView->updateView(getQtkWidget()->getScene()); ui_->qtk__TreeView->updateView(getQtkWidget()->getScene());
} }

View File

@@ -69,7 +69,7 @@ class MainWindow : public QMainWindow {
* Trigger a refresh for widgets related to a scene that has been updated. * Trigger a refresh for widgets related to a scene that has been updated.
* @param sceneName The name of the scene that has been modified. * @param sceneName The name of the scene that has been modified.
*/ */
void refreshScene(const QString & sceneName); void refreshScene(QString sceneName);
private: private:
/*************************************************************************** /***************************************************************************

View File

@@ -37,10 +37,10 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Object details and configuration panel.</string> <string>A custom widget tool tip.</string>
</property> </property>
<property name="whatsThis"> <property name="whatsThis">
<string>When an object is double-clicked in the TreeView for a scene, this panel will display relevant details and options.</string> <string>Custom widget what's this?</string>
</property> </property>
</widget> </widget>
</item> </item>
@@ -66,10 +66,10 @@
<item> <item>
<widget class="Qtk::QtkWidget" name="qtk::QtkWidget"> <widget class="Qtk::QtkWidget" name="qtk::QtkWidget">
<property name="toolTip"> <property name="toolTip">
<string/> <string>A custom widget tool tip.</string>
</property> </property>
<property name="whatsThis"> <property name="whatsThis">
<string>Qtk scene view rendered using OpenGL.</string> <string>Custom widget what's this?</string>
</property> </property>
</widget> </widget>
</item> </item>
@@ -91,10 +91,10 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>TreeView of objects within the current scene.</string> <string>A custom widget tool tip.</string>
</property> </property>
<property name="whatsThis"> <property name="whatsThis">
<string>TreeView of objects within the current scene. Double-click to select an object and snap to it's position.</string> <string>Custom widget what's this?</string>
</property> </property>
</widget> </widget>
</item> </item>

View File

@@ -16,9 +16,8 @@ using namespace Qtk;
QtkScene::QtkScene(Qtk::Scene * scene) : Qtk::SceneInterface(scene) { QtkScene::QtkScene(Qtk::Scene * scene) : Qtk::SceneInterface(scene) {
setSceneName("Qtk Scene"); setSceneName("Qtk Scene");
getCamera().setTranslation({0.0f, 0.0f, 20.0f}); getCamera().getTransform().setTranslation(0.0f, 0.0f, 20.0f);
getCamera().setRotation( getCamera().getTransform().setRotation(-5.0f, 0.0f, 1.0f, 0.0f);
QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, -5.0f));
} }
QtkScene::~QtkScene() { QtkScene::~QtkScene() {
@@ -90,7 +89,7 @@ void QtkScene::init() {
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(0.0f, 1.0f, 0.0f, -110.0f); model->getTransform().rotate(-110.0f, 0.0f, 1.0f, 0.0f);
model = addObject( model = addObject(
new Qtk::Model("alien", ":/models/models/alien-hominid/alien.obj")); new Qtk::Model("alien", ":/models/models/alien-hominid/alien.obj"));
@@ -100,8 +99,8 @@ void QtkScene::init() {
model = addObject( model = addObject(
new Qtk::Model("My scythe", ":/models/models/scythe/scythe.obj")); new Qtk::Model("My 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(1.0f, 0.0f, 0.0f, -90.0f); model->getTransform().rotate(-90.0f, 1.0f, 0.0f, 0.0f);
model->getTransform().rotate(0.0f, 1.0f, 0.0f, 90.0f); model->getTransform().rotate(90.0f, 0.0f, 1.0f, 0.0f);
model = addObject( model = addObject(
new Qtk::Model("masterChief", ":/models/models/spartan/spartan.obj")); new Qtk::Model("masterChief", ":/models/models/spartan/spartan.obj"));
@@ -332,14 +331,14 @@ void QtkScene::init() {
mesh->reallocateNormals(mesh->getNormals()); mesh->reallocateNormals(mesh->getNormals());
mesh->reallocateTexCoords(mesh->getTexCoords(), 3); mesh->reallocateTexCoords(mesh->getTexCoords(), 3);
mesh->releaseShaders(); mesh->releaseShaders();
mesh->getTransform().rotate(0.0f, 1.0f, 0.0f, 45.0f); mesh->getTransform().rotate(45.0f, 0.0f, 1.0f, 0.0f);
// Texturing a cube using a cube map // Texturing a cube using a cube map
// + Cube map texturing works with both QTK_DRAW_ARRAYS and QTK_DRAW_ELEMENTS // + Cube map texturing works with both QTK_DRAW_ARRAYS and QTK_DRAW_ELEMENTS
mesh = mesh =
addObject(new Qtk::MeshRenderer("testCubeMap", Cube(QTK_DRAW_ELEMENTS))); addObject(new Qtk::MeshRenderer("testCubeMap", Cube(QTK_DRAW_ELEMENTS)));
mesh->getTransform().setTranslation(-3.0f, 1.0f, -2.0f); mesh->getTransform().setTranslation(-3.0f, 1.0f, -2.0f);
mesh->getTransform().setRotation(0.0f, 1.0f, 0.0f, 45.0f); mesh->getTransform().setRotation(45.0f, 0.0f, 1.0f, 0.0f);
mesh->setShaders( mesh->setShaders(
":/shaders/texture-cubemap.vert", ":/shaders/texture-cubemap.frag"); ":/shaders/texture-cubemap.vert", ":/shaders/texture-cubemap.frag");
mesh->setCubeMap(":/textures/crate.png"); mesh->setCubeMap(":/textures/crate.png");
@@ -440,10 +439,10 @@ void QtkScene::draw() {
void QtkScene::update() { void QtkScene::update() {
auto mySpartan = Model::getInstance("My spartan"); auto mySpartan = Model::getInstance("My spartan");
mySpartan->getTransform().rotate(0.0f, 1.0f, 0.0f, 0.75f); mySpartan->getTransform().rotate(0.75f, 0.0f, 1.0f, 0.0f);
auto myCube = MeshRenderer::getInstance("My cube"); auto myCube = MeshRenderer::getInstance("My cube");
myCube->getTransform().rotate(-0.0f, 1.0f, 0.0f, 0.75f); myCube->getTransform().rotate(-0.75f, 0.0f, 1.0f, 0.0f);
auto position = MeshRenderer::getInstance("alienTestLight") auto position = MeshRenderer::getInstance("alienTestLight")
->getTransform() ->getTransform()
@@ -457,7 +456,7 @@ void QtkScene::update() {
alien->setUniform("uMVP.model", posMatrix); alien->setUniform("uMVP.model", posMatrix);
alien->setUniform("uMVP.view", QtkScene::getCamera().toMatrix()); alien->setUniform("uMVP.view", QtkScene::getCamera().toMatrix());
alien->setUniform("uMVP.projection", QtkScene::getProjectionMatrix()); alien->setUniform("uMVP.projection", QtkScene::getProjectionMatrix());
alien->getTransform().rotate(0.0f, 1.0f, 0.0f, 0.75f); alien->getTransform().rotate(0.75f, 0.0f, 1.0f, 0.0f);
position = MeshRenderer::getInstance("spartanTestLight") position = MeshRenderer::getInstance("spartanTestLight")
->getTransform() ->getTransform()
@@ -471,10 +470,10 @@ void QtkScene::update() {
spartan->setUniform("uMVP.model", posMatrix); spartan->setUniform("uMVP.model", posMatrix);
spartan->setUniform("uMVP.view", QtkScene::getCamera().toMatrix()); spartan->setUniform("uMVP.view", QtkScene::getCamera().toMatrix());
spartan->setUniform("uMVP.projection", QtkScene::getProjectionMatrix()); spartan->setUniform("uMVP.projection", QtkScene::getProjectionMatrix());
spartan->getTransform().rotate(0.0f, 1.0f, 0.0f, 0.75f); spartan->getTransform().rotate(0.75f, 0.0f, 1.0f, 0.0f);
auto phong = MeshRenderer::getInstance("testPhong"); auto phong = MeshRenderer::getInstance("testPhong");
phong->getTransform().rotate(1.0f, 0.5f, 0.0f, 0.75f); phong->getTransform().rotate(0.75f, 1.0f, 0.5f, 0.0f);
phong->bindShaders(); phong->bindShaders();
position = position =
MeshRenderer::getInstance("testLight")->getTransform().getTranslation(); MeshRenderer::getInstance("testLight")->getTransform().getTranslation();
@@ -489,27 +488,27 @@ void QtkScene::update() {
phong->releaseShaders(); phong->releaseShaders();
// Rotate lighting example cubes // Rotate lighting example cubes
mTestPhong->getTransform().rotate(0.5f, 0.3f, 0.2f, 0.75f); mTestPhong->getTransform().rotate(0.75f, 0.5f, 0.3f, 0.2f);
MeshRenderer::getInstance("noLight")->getTransform().rotate( MeshRenderer::getInstance("noLight")->getTransform().rotate(
0.5f, 0.3f, 0.2f, 0.75f); 0.75f, 0.5f, 0.3f, 0.2f);
mTestAmbient->getTransform().rotate(0.5f, 0.3f, 0.2f, 0.75f); mTestAmbient->getTransform().rotate(0.75f, 0.5f, 0.3f, 0.2f);
mTestDiffuse->getTransform().rotate(0.5f, 0.3f, 0.2f, 0.75f); mTestDiffuse->getTransform().rotate(0.75f, 0.5f, 0.3f, 0.2f);
mTestSpecular->getTransform().rotate(0.5f, 0.3f, 0.2f, 0.75f); mTestSpecular->getTransform().rotate(0.75f, 0.5f, 0.3f, 0.2f);
// Examples of various translations and rotations // Examples of various translations and rotations
// Rotate in multiple directions simultaneously // Rotate in multiple directions simultaneously
MeshRenderer::getInstance("rgbNormalsCube") MeshRenderer::getInstance("rgbNormalsCube")
->getTransform() ->getTransform()
.rotate(0.2f, 0.4f, 0.6f, 0.75f); .rotate(0.75f, 0.2f, 0.4f, 0.6f);
// Pitch forward and roll sideways // Pitch forward and roll sideways
MeshRenderer::getInstance("leftTriangle") MeshRenderer::getInstance("leftTriangle")
->getTransform() ->getTransform()
.rotate(1.0f, 0.0f, 0.0f, 0.75f); .rotate(0.75f, 1.0f, 0.0f, 0.0f);
MeshRenderer::getInstance("rightTriangle") MeshRenderer::getInstance("rightTriangle")
->getTransform() ->getTransform()
.rotate(0.0f, 0.0f, 1.0f, 0.75f); .rotate(0.75f, 0.0f, 0.0f, 1.0f);
// Move between two positions over time // Move between two positions over time
static float translateX = 0.025f; static float translateX = 0.025f;
@@ -530,15 +529,15 @@ void QtkScene::update() {
// And lets rotate the triangles in two directions at once // And lets rotate the triangles in two directions at once
MeshRenderer::getInstance("topTriangle") MeshRenderer::getInstance("topTriangle")
->getTransform() ->getTransform()
.rotate(0.2f, 0.0f, 0.4f, 0.75f); .rotate(0.75f, 0.2f, 0.0f, 0.4f);
MeshRenderer::getInstance("bottomTriangle") MeshRenderer::getInstance("bottomTriangle")
->getTransform() ->getTransform()
.rotate(0.0f, 0.2f, 0.4f, 0.75f); .rotate(0.75f, 0.0f, 0.2f, 0.4f);
// And make the bottom triangle green, instead of RGB // And make the bottom triangle green, instead of RGB
// Rotate center cube in several directions simultaneously // Rotate center cube in several directions simultaneously
// + Not subject to gimbal lock since we are using quaternions :) // + Not subject to gimbal lock since we are using quaternions :)
MeshRenderer::getInstance("centerCube") MeshRenderer::getInstance("centerCube")
->getTransform() ->getTransform()
.rotate(0.2f, 0.4f, 0.6f, 0.75f); .rotate(0.75f, 0.2f, 0.4f, 0.6f);
} }

View File

@@ -10,12 +10,16 @@
#include <QMimeData> #include <QMimeData>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <qtk/input.h>
#include <qtk/scene.h>
#include <qtk/shape.h>
#include <QVBoxLayout>
#include <qtk/input.h> #include <qtk/input.h>
#include <qtk/scene.h> #include <qtk/scene.h>
#include <qtk/shape.h> #include <qtk/shape.h>
#include "debugconsole.h" #include "debugconsole.h"
#include "qtk/qtkmessagelogger.h"
#include "qtkmainwindow.h" #include "qtkmainwindow.h"
#include "qtkwidget.h" #include "qtkwidget.h"
@@ -31,9 +35,8 @@ QtkWidget::QtkWidget(QWidget * parent, const QString & name) :
QtkWidget(parent, name, Q_NULLPTR) {} QtkWidget(parent, name, Q_NULLPTR) {}
QtkWidget::QtkWidget(QWidget * parent, const QString & name, Scene * scene) : QtkWidget::QtkWidget(QWidget * parent, const QString & name, Scene * scene) :
QOpenGLWidget(parent), mDebugLogger(new QOpenGLDebugLogger(this)), QOpenGLWidget(parent), mDebugLogger(Q_NULLPTR),
mConsole(new DebugConsole(this, name)), mScene(Q_NULLPTR), mConsole(new DebugConsole(this, name)), mScene(Q_NULLPTR) {
mLogger(new Qtk::Logger(this)) {
setAcceptDrops(true); setAcceptDrops(true);
setScene(scene); setScene(scene);
setObjectName(name); setObjectName(name);
@@ -74,22 +77,17 @@ void QtkWidget::initializeGL() {
// Connect the frameSwapped signal to call the update() function // Connect the frameSwapped signal to call the update() function
connect(this, SIGNAL(frameSwapped()), this, SLOT(update())); connect(this, SIGNAL(frameSwapped()), this, SLOT(update()));
toggleConsole();
// Initialize OpenGL debug context // Initialize OpenGL debug context
mDebugLogger = new QOpenGLDebugLogger(this);
if(mDebugLogger->initialize()) { if(mDebugLogger->initialize()) {
qDebug() << "GL_DEBUG Debug Logger" << mDebugLogger << "\n";
connect( connect(
mDebugLogger, SIGNAL(messageLogged(QOpenGLDebugMessage)), mLogger, mDebugLogger, SIGNAL(messageLogged(QOpenGLDebugMessage)), this,
SLOT(log(QOpenGLDebugMessage))); SLOT(messageLogged(QOpenGLDebugMessage)));
// connect( // connect(
// Qtk::QtkMessageLogger::get(), // mDebugLogger, SIGNAL(messageLogged(QOpenGLDebugMessage)),
// &Qtk::QtkMessageLogger::messageLogged, mLogger, // mConsole, SLOT(sendLog(QOpenGLDebugMessage)));
// &Qtk::Logger::parseError);
mDebugLogger->startLogging(); mDebugLogger->startLogging();
QString msg;
QTextStream stream(&msg);
stream << "Logging started on GL_DEBUG Debug Logger: " << mDebugLogger;
mDebugLogger->logMessage(QOpenGLDebugMessage::createApplicationMessage(
stream.string()->toStdString().c_str()));
} }
printContextInformation(); printContextInformation();
@@ -159,8 +157,8 @@ void QtkWidget::dragEnterEvent(QDragEnterEvent * event) {
void QtkWidget::dropEvent(QDropEvent * event) { void QtkWidget::dropEvent(QDropEvent * event) {
mConsole->sendLog(event->mimeData()->text()); mConsole->sendLog(event->mimeData()->text());
if(event->mimeData()->hasUrls()) {
auto urls = event->mimeData()->urls(); auto urls = event->mimeData()->urls();
if(!urls.isEmpty()) {
if(urls.size() > 1) { if(urls.size() > 1) {
qDebug() << "Cannot accept drop of multiple files."; qDebug() << "Cannot accept drop of multiple files.";
event->ignore(); event->ignore();
@@ -173,7 +171,7 @@ void QtkWidget::dropEvent(QDropEvent * event) {
mScene->loadModel(url); mScene->loadModel(url);
event->acceptProposedAction(); event->acceptProposedAction();
} else { } else {
qDebug() << "Unsupported file type: " + url.fileName() + "\n"; qDebug() << "Unsupported file type.";
event->ignore(); event->ignore();
} }
} }
@@ -214,6 +212,74 @@ void QtkWidget::update() {
QWidget::update(); QWidget::update();
} }
void QtkWidget::messageLogged(const QOpenGLDebugMessage & msg) {
QString error;
DebugContext context;
// Format based on severity
switch(msg.severity()) {
case QOpenGLDebugMessage::NotificationSeverity:
error += "--";
context = Status;
break;
case QOpenGLDebugMessage::HighSeverity:
error += "!!";
context = Fatal;
break;
case QOpenGLDebugMessage::MediumSeverity:
error += "!~";
context = Error;
break;
case QOpenGLDebugMessage::LowSeverity:
error += "~~";
context = Warn;
break;
}
error += " (";
// Format based on source
#define CASE(c) \
case QOpenGLDebugMessage::c: \
error += #c; \
break
switch(msg.source()) {
CASE(APISource);
CASE(WindowSystemSource);
CASE(ShaderCompilerSource);
CASE(ThirdPartySource);
CASE(ApplicationSource);
CASE(OtherSource);
CASE(InvalidSource);
}
#undef CASE
error += " : ";
// Format based on type
#define CASE(c) \
case QOpenGLDebugMessage::c: \
error += #c; \
break
switch(msg.type()) {
CASE(InvalidType);
CASE(ErrorType);
CASE(DeprecatedBehaviorType);
CASE(UndefinedBehaviorType);
CASE(PortabilityType);
CASE(PerformanceType);
CASE(OtherType);
CASE(MarkerType);
CASE(GroupPushType);
CASE(GroupPopType);
}
#undef CASE
error += ")\n" + msg.message() + "\n";
qDebug() << qPrintable(error);
sendLog("(OpenGL) " + error.replace("\n", "\n(OpenGL) "), context);
}
/******************************************************************************* /*******************************************************************************
* Private Methods * Private Methods
******************************************************************************/ ******************************************************************************/
@@ -230,10 +296,10 @@ void QtkWidget::updateCameraInput() {
static const float rotSpeed = 0.5f; static const float rotSpeed = 0.5f;
// Handle rotations // Handle rotations
Scene::getCamera().rotate(QQuaternion::fromAxisAndAngle( Scene::getCamera().getTransform().rotate(
Camera3D::LocalUp, -rotSpeed * Input::mouseDelta().x())); -rotSpeed * Input::mouseDelta().x(), Camera3D::LocalUp);
Scene::getCamera().rotate(QQuaternion::fromAxisAndAngle( Scene::getCamera().getTransform().rotate(
Scene::getCamera().getRight(), -rotSpeed * Input::mouseDelta().y())); -rotSpeed * Input::mouseDelta().y(), Scene::getCamera().getRight());
// Handle translations // Handle translations
QVector3D translation; QVector3D translation;
@@ -255,7 +321,7 @@ void QtkWidget::updateCameraInput() {
if(Input::keyPressed(Qt::Key_E)) { if(Input::keyPressed(Qt::Key_E)) {
translation += Scene::getCamera().getUp() / 2.0f; translation += Scene::getCamera().getUp() / 2.0f;
} }
Scene::getCamera().translate(transSpeed * translation); Scene::getCamera().getTransform().translate(transSpeed * translation);
} }
} }
@@ -288,5 +354,6 @@ void QtkWidget::printContextInformation() {
auto message = QString(glType) + glVersion + "(" + glProfile + ")" auto message = QString(glType) + glVersion + "(" + glProfile + ")"
+ "\nOpenGL Vendor: " + glVendor + "\nOpenGL Vendor: " + glVendor
+ "\nRendering Device: " + glRenderer; + "\nRendering Device: " + glRenderer;
emit sendLog("(OpenGL) " + message.replace("\n", "\n(OpenGL) "), Status); qDebug() << qPrintable(message);
sendLog("(OpenGL) " + message.replace("\n", "\n(OpenGL) "), Status);
} }

View File

@@ -19,7 +19,6 @@
#include <qtk/qtkapi.h> #include <qtk/qtkapi.h>
#include <qtk/scene.h> #include <qtk/scene.h>
#include "logger.h"
namespace Qtk { namespace Qtk {
class DebugConsole; class DebugConsole;
@@ -108,8 +107,6 @@ namespace Qtk {
return mDebugLogger; return mDebugLogger;
} }
inline Logger * getLogger() { return mLogger; }
/************************************************************************* /*************************************************************************
* Setters * Setters
************************************************************************/ ************************************************************************/
@@ -132,7 +129,7 @@ namespace Qtk {
* @param message The message to log. * @param message The message to log.
* @param context The context of the log message. * @param context The context of the log message.
*/ */
void sendLog(const QString & message, Qtk::DebugContext context = Status); void sendLog(const QString & message, DebugContext context = Status);
// TODO: Use this signal in treeview and toolbox to update object // TODO: Use this signal in treeview and toolbox to update object
// properties // properties
@@ -181,7 +178,7 @@ namespace Qtk {
* *
* @param msg The message logged. * @param msg The message logged.
*/ */
// void messageLogged(const QOpenGLDebugMessage & msg); void messageLogged(const QOpenGLDebugMessage & msg);
private: private:
/************************************************************************* /*************************************************************************
@@ -207,7 +204,6 @@ namespace Qtk {
* Private Members * Private Members
************************************************************************/ ************************************************************************/
Qtk::Logger * mLogger;
QOpenGLDebugLogger * mDebugLogger; QOpenGLDebugLogger * mDebugLogger;
Qtk::Scene * mScene; Qtk::Scene * mScene;
Qtk::DebugConsole * mConsole; Qtk::DebugConsole * mConsole;

View File

@@ -22,6 +22,7 @@ ToolBox::ToolBox(QWidget * parent) : QDockWidget(parent), ui(new Ui::ToolBox) {
} }
void ToolBox::updateFocus(const QString & name) { void ToolBox::updateFocus(const QString & name) {
qDebug() << "Called updateFocus on Toolbox.";
auto object = auto object =
MainWindow::getMainWindow()->getQtkWidget()->getScene()->getObject(name); MainWindow::getMainWindow()->getQtkWidget()->getScene()->getObject(name);
if(object != Q_NULLPTR) { if(object != Q_NULLPTR) {

View File

@@ -46,6 +46,7 @@ void Qtk::TreeView::updateView(const Qtk::Scene * scene) {
void Qtk::TreeView::itemFocus(QTreeWidgetItem * item, int column) { void Qtk::TreeView::itemFocus(QTreeWidgetItem * item, int column) {
QString name = item->text(column); QString name = item->text(column);
auto scene = MainWindow::getMainWindow()->getQtkWidget()->getScene(); auto scene = MainWindow::getMainWindow()->getQtkWidget()->getScene();
auto & transform = scene->getCamera().getTransform();
auto object = scene->getObject(name); auto object = scene->getObject(name);
Transform3D * objectTransform; Transform3D * objectTransform;
// If the object is a mesh or model, focus the camera on it. // If the object is a mesh or model, focus the camera on it.
@@ -58,11 +59,13 @@ void Qtk::TreeView::itemFocus(QTreeWidgetItem * item, int column) {
objectTransform = &dynamic_cast<Model *>(object)->getTransform(); objectTransform = &dynamic_cast<Model *>(object)->getTransform();
} }
auto focusScale = objectTransform->getScale(); auto focusScale = objectTransform->getScale();
float width = focusScale.x() / 2.0f;
float height = focusScale.y() / 2.0f; float height = focusScale.y() / 2.0f;
QVector3D pos = objectTransform->getTranslation(); QVector3D pos = objectTransform->getTranslation();
// pos.setX(pos.x() + width);
pos.setY(pos.y() + height); pos.setY(pos.y() + height);
Qtk::Scene::getCamera().setTranslation(pos); transform.setTranslation(pos);
Qtk::Scene::getCamera().translate({0.0f, 0.0f, 3.0f}); transform.translate(0.0f, 0.0f, 3.0f);
// Emit signal from qtk widget for new object focus. Triggers GUI updates. // Emit signal from qtk widget for new object focus. Triggers GUI updates.
emit MainWindow::getMainWindow()->getQtkWidget()->objectFocusChanged(name); emit MainWindow::getMainWindow()->getQtkWidget()->objectFocusChanged(name);

View File

@@ -24,8 +24,6 @@ set(
skybox.h skybox.h
texture.h texture.h
transform3D.h transform3D.h
qtkmessagelogger.h
../app/logger.h
) )
set( set(
@@ -43,8 +41,6 @@ set(
skybox.cpp skybox.cpp
texture.cpp texture.cpp
transform3D.cpp transform3D.cpp
qtkmessagelogger.cpp
../app/logger.cpp
) )
qt6_add_big_resources(QTK_LIBRARY_SOURCES "${QTK_RESOURCES}/resources.qrc") qt6_add_big_resources(QTK_LIBRARY_SOURCES "${QTK_RESOURCES}/resources.qrc")
@@ -72,9 +68,9 @@ target_link_libraries(
Qt6::Core Qt6::OpenGLWidgets Qt6::Widgets Qt6::Core Qt6::OpenGLWidgets Qt6::Widgets
) )
if(QTK_SUBMODULES OR NOT QTK_ASSIMP_NEW_INTERFACE) if(QTK_SUBMODULES OR NOT ASSIMP_NEW_INTERFACE)
target_link_libraries(qtk_library PUBLIC assimp) target_link_libraries(qtk_library PUBLIC assimp)
elseif(QTK_ASSIMP_NEW_INTERFACE) elseif(ASSIMP_NEW_INTERFACE)
target_link_libraries(qtk_library PUBLIC assimp::assimp) target_link_libraries(qtk_library PUBLIC assimp::assimp)
endif() endif()

View File

@@ -29,3 +29,28 @@ const QMatrix4x4 & Camera3D::toMatrix() {
mWorld.translate(-mTransform.getTranslation()); mWorld.translate(-mTransform.getTranslation());
return mWorld; return mWorld;
} }
/*******************************************************************************
* Qt Streams
******************************************************************************/
QDataStream & operator<<(QDataStream & out, Camera3D & transform) {
out << transform.getTransform();
return out;
}
QDataStream & operator>>(QDataStream & in, Camera3D & transform) {
in >> transform.getTransform();
return in;
}
QDebug operator<<(QDebug dbg, const Camera3D & transform) {
dbg << "Camera3D\n{\n";
dbg << "Position: <" << transform.getTranslation().x() << ", "
<< transform.getTranslation().y() << ", "
<< transform.getTranslation().z() << ">\n";
dbg << "Rotation: <" << transform.getRotation().x() << ", "
<< transform.getRotation().y() << ", " << transform.getRotation().z()
<< " | " << transform.getRotation().scalar() << ">\n}";
return dbg;
}

View File

@@ -32,9 +32,7 @@ namespace Qtk {
/** /**
* @return Transform3D associated with this camera. * @return Transform3D associated with this camera.
*/ */
[[nodiscard]] inline const Transform3D & getTransform() const { inline Transform3D & getTransform() { return mTransform; }
return mTransform;
}
/** /**
* @return Current translation of the camera as a QVector3D. * @return Current translation of the camera as a QVector3D.
@@ -80,85 +78,33 @@ namespace Qtk {
*/ */
const QMatrix4x4 & toMatrix(); const QMatrix4x4 & toMatrix();
/**
* Set the translation for this camera.
* TODO: Replace these methods by inheriting from a base class.
*
* @param translation QVector3D for the new translation.
*/
inline void setTranslation(const QVector3D & translation) {
mTransform.setTranslation(translation);
}
/**
* Set the rotation for this camera.
*
* @param rotation QQuaternion for the new rotation.
*/
inline void setRotation(const QQuaternion & rotation) {
mTransform.setRotation(rotation);
}
/**
* Sets a rotation upon an axis represented by the 3D vector (x, y, z)
*
* @param ax X axis to set angle for.
* @param ay Y axis to set angle for.
* @param az Z axis to set angle for.
* @param angle Angle to set rotation.
*/
inline void setRotation(float ax, float ay, float az, float angle) {
mTransform.setRotation(ax, ay, az, angle);
}
/**
* Translate the camera by the given position.
*
* @param position QVector3D for the position to translate by.
*/
inline void translate(const QVector3D & position) {
mTransform.translate(position);
}
/**
* Rotate the camera by the given rotation.
*
* @param rotation QQaternion for the rotation to apply.
*/
inline void rotate(const QQuaternion & rotation) {
mTransform.rotate(rotation);
}
/**
* Sets a rotation upon an axis represented by the 3D vector (x, y, z)
*
* @param ax X axis to set angle for.
* @param ay Y axis to set angle for.
* @param az Z axis to set angle for.
* @param angle Angle to set rotation.
*/
inline void rotate(float ax, float ay, float az, float angle) {
mTransform.rotate(ax, ay, az, angle);
}
private: private:
/*************************************************************************
* Private Methods
************************************************************************/
#ifndef QT_NO_DATASTREAM
friend QDataStream & operator<<(QDataStream & out, Camera3D & transform);
friend QDataStream & operator>>(QDataStream & in, Camera3D & transform);
#endif
/************************************************************************* /*************************************************************************
* Private Members * Private Members
************************************************************************/ ************************************************************************/
Transform3D mTransform; Transform3D mTransform;
QMatrix4x4 mWorld; QMatrix4x4 mWorld;
/*************************************************************************
* Qt Streams
************************************************************************/
#ifndef QT_NO_DATASTREAM
friend QDataStream & operator<<(
QDataStream & out, const Camera3D & camera);
friend QDataStream & operator>>(QDataStream & in, Camera3D & camera);
#endif
}; };
// Qt Streams
#ifndef QT_NO_DATASTREAM
QDataStream & operator<<(QDataStream & out, const Camera3D & transform);
QDataStream & operator>>(QDataStream & in, Camera3D & transform);
#endif
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const Camera3D & transform);
#endif
} // namespace Qtk } // namespace Qtk
Q_DECLARE_TYPEINFO(Qtk::Camera3D, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(Qtk::Camera3D, Q_MOVABLE_TYPE);

View File

@@ -43,7 +43,7 @@ void Model::flipTexture(const std::string & fileName, bool flipX, bool flipY) {
texture.mTexture->destroy(); texture.mTexture->destroy();
texture.mTexture->create(); texture.mTexture->create();
texture.mTexture->setData( texture.mTexture->setData(
OpenGLTextureFactory::initImage(fullPath.c_str(), flipX, flipY)); *OpenGLTextureFactory::initImage(fullPath.c_str(), flipX, flipY));
modified = true; modified = true;
} }
} }
@@ -238,7 +238,7 @@ ModelMesh::Textures Model::loadMaterialTextures(
// Add the texture to the textures container // Add the texture to the textures container
textures.push_back(texture); textures.push_back(texture);
// Add the texture to the loaded textures to avoid loading it twice // Add the texture to the loaded textures to avoid loading it twice
mTexturesLoaded.push_back(textures.back()); mTexturesLoaded.push_back(texture);
} }
} }

View File

@@ -52,10 +52,6 @@ void ModelMesh::draw(QOpenGLShaderProgram & shader) {
shader.setUniformValue((name + number).c_str(), i); shader.setUniformValue((name + number).c_str(), i);
} }
// Always reset active texture to GL_TEXTURE0 before we draw.
// This is important for models with no textures.
glActiveTexture(GL_TEXTURE0);
// Draw the mesh // Draw the mesh
glDrawElements( glDrawElements(
GL_TRIANGLES, mIndices.size(), GL_UNSIGNED_INT, mIndices.data()); GL_TRIANGLES, mIndices.size(), GL_UNSIGNED_INT, mIndices.data());
@@ -66,6 +62,7 @@ void ModelMesh::draw(QOpenGLShaderProgram & shader) {
} }
shader.release(); shader.release();
mVAO->release(); mVAO->release();
glActiveTexture(GL_TEXTURE0);
} }
/******************************************************************************* /*******************************************************************************

View File

@@ -30,21 +30,6 @@ namespace Qtk {
* Struct to store model textures. 3D Models may have multiple. * Struct to store model textures. 3D Models may have multiple.
*/ */
struct QTKAPI ModelTexture { struct QTKAPI ModelTexture {
ModelTexture() = default;
/**
* Construct a ModelTexture.
*
* @param id Texture ID for this texture.
* @param type Type of texture in string format.
* @param path Path to the texture on disk.
*/
ModelTexture(const std::string & type, const std::string & path) :
mType(type), mPath(path) {
mTexture = OpenGLTextureFactory::initTexture(path.c_str());
mID = mTexture->textureId();
}
/** Texture ID for for this texture. */ /** Texture ID for for this texture. */
GLuint mID {}; GLuint mID {};
QOpenGLTexture * mTexture {}; QOpenGLTexture * mTexture {};

View File

@@ -22,8 +22,6 @@
#define QTKAPI #define QTKAPI
#endif #endif
#include "qtk/qtkmessagelogger.h"
/** /**
* Initialize Qt resources required by the Qtk library. * Initialize Qt resources required by the Qtk library.
* 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.
@@ -37,7 +35,7 @@ namespace Qtk {
/** /**
* Flag to set context for debug messages. * Flag to set context for debug messages.
*/ */
enum DebugContext { Status, Debug, Warn, Error, Fatal, Invalid, Any }; enum DebugContext { Status, Debug, Warn, Error, Fatal };
/** /**
* Find top level parent for a widget. * Find top level parent for a widget.

View File

@@ -17,23 +17,17 @@ using namespace Qtk;
QtkIOStream::QtkIOStream(const char * pFile, const char * pMode) : QtkIOStream::QtkIOStream(const char * pFile, const char * pMode) :
mFile(pFile) { mFile(pFile) {
QString mode(pMode); QString mode(pMode);
bool open = false; bool read = mode.contains('r');
if(mode == "w" || mode == "wb") { bool write = mode.contains('w');
open = mFile.open(QIODeviceBase::WriteOnly); if(read && write) {
} else if(mode == "r" || mode == "rb") { mFile.open(QIODevice::ReadWrite);
open = mFile.open(QIODeviceBase::ReadOnly); } else if(read) {
} else if(mode == "wt") { mFile.open(QIODevice::ReadOnly);
open = mFile.open(QIODeviceBase::WriteOnly | QIODeviceBase::Text); } else if(write) {
} else if(mode == "rt") { mFile.open(QIODevice::WriteOnly);
open = mFile.open(QIODeviceBase::ReadOnly | QIODeviceBase::Text);
} else { } else {
open = false;
qDebug() << "[Qtk::QtkIOStream] Invalid file open mode: " << mode << "\n"; qDebug() << "[Qtk::QtkIOStream] Invalid file open mode: " << mode << "\n";
} }
if(!open) {
qDebug() << "[Qtk::QtkIOStream] Could not open file: " << QString(pFile)
<< "\n";
}
} }
/******************************************************************************* /*******************************************************************************
@@ -41,24 +35,34 @@ QtkIOStream::QtkIOStream(const char * pFile, const char * pMode) :
******************************************************************************/ ******************************************************************************/
size_t QtkIOStream::Read(void * pvBuffer, size_t pSize, size_t pCount) { size_t QtkIOStream::Read(void * pvBuffer, size_t pSize, size_t pCount) {
qint64 readSize = mFile.read((char *)pvBuffer, pSize * pCount); size_t read = 0;
do {
auto readSize = mFile.read((char *)pvBuffer + read, pSize);
if(readSize < 0) { if(readSize < 0) {
qDebug() << "[Qtk::QtkIOStream] Failed to read (" << pSize qDebug() << "[Qtk::QtkIOStream] Failed to read (" << pSize
<< ") bytes from file at: " << mFile.filesystemFileName().c_str() << ") bytes from file at: " << mFile.filesystemFileName().c_str()
<< "\n"; << "\n";
return -1; return -1;
} }
return readSize; read += readSize;
} while(pCount--);
return read;
} }
size_t QtkIOStream::Write(const void * pvBuffer, size_t pSize, size_t pCount) { size_t QtkIOStream::Write(const void * pvBuffer, size_t pSize, size_t pCount) {
qint64 writeSize = mFile.write((char *)pvBuffer, pSize * pCount); size_t wrote = 0;
do {
auto writeSize = mFile.write((char *)pvBuffer + wrote, pSize);
if(writeSize < 0) { if(writeSize < 0) {
qDebug() << "[Qtk::QtkIOStream] Failed to write buffer with size (" << pSize qDebug() << "[Qtk::QtkIOStream] Failed to write buffer with size ("
<< ") to file at: " << mFile.filesystemFileName().c_str() << "\n"; << pSize
<< ") to file at: " << mFile.filesystemFileName().c_str()
<< "\n";
return -1; return -1;
} }
return writeSize; wrote += writeSize;
} while(pCount--);
return wrote;
} }
aiReturn QtkIOStream::Seek(size_t pOffset, aiOrigin pOrigin) { aiReturn QtkIOStream::Seek(size_t pOffset, aiOrigin pOrigin) {

View File

@@ -7,7 +7,6 @@
##############################################################################*/ ##############################################################################*/
#include "qtkiosystem.h" #include "qtkiosystem.h"
#include <QDir>
using namespace Qtk; using namespace Qtk;
@@ -20,11 +19,15 @@ bool QtkIOSystem::Exists(const char * pFile) const {
} }
char QtkIOSystem::getOsSeparator() const { char QtkIOSystem::getOsSeparator() const {
return QDir::separator().toLatin1(); #ifndef _WIN32
return '/';
#else
return '\\';
#endif
} }
Assimp::IOStream * QtkIOSystem::Open(const char * pFile, const char * pMode) { Assimp::IOStream * QtkIOSystem::Open(const char * pFile, const char * pMode) {
if(!Exists(pFile)) { if(!QFileInfo::exists(pFile)) {
qDebug() << "[Qtk::QtkIOSystem] failed to open file: " << pFile << "\n"; qDebug() << "[Qtk::QtkIOSystem] failed to open file: " << pFile << "\n";
return nullptr; return nullptr;
} }

View File

@@ -1,61 +0,0 @@
#include "qtkmessagelogger.h"
#include "camera3d.h"
#include "transform3D.h"
Qtk::QtkDebug Qtk::QtkDebug::operator<<(const Qtk::Transform3D & transform) {}
#ifndef QT_NO_DEBUG_STREAM
QDebug Qtk::operator<<(QDebug dbg, const Qtk::Transform3D & transform) {
dbg << "Transform3D\n{\n";
dbg << "Position: <" << transform.getTranslation().x() << ", "
<< transform.getTranslation().y() << ", "
<< transform.getTranslation().z() << ">\n";
dbg << "Scale: <" << transform.getScale().x() << ", "
<< transform.getScale().y() << ", " << transform.getScale().z() << ">\n";
dbg << "Rotation: <" << transform.getRotation().x() << ", "
<< transform.getRotation().y() << ", " << transform.getRotation().z()
<< " | " << transform.getRotation().scalar() << ">\n}";
return dbg;
}
QDebug Qtk::operator<<(QDebug dbg, const Qtk::Camera3D & transform) {
dbg << "Camera3D\n{\n";
dbg << "Position: <" << transform.getTranslation().x() << ", "
<< transform.getTranslation().y() << ", "
<< transform.getTranslation().z() << ">\n";
dbg << "Rotation: <" << transform.getRotation().x() << ", "
<< transform.getRotation().y() << ", " << transform.getRotation().z()
<< " | " << transform.getRotation().scalar() << ">\n}";
return dbg;
}
#endif
#ifndef QT_NO_DATASTREAM
QDataStream & Qtk::operator<<(
QDataStream & out, const Qtk::Transform3D & transform) {
out << transform.mTranslation;
out << transform.mScale;
out << transform.mRotation;
return out;
}
QDataStream & Qtk::operator>>(QDataStream & in, Qtk::Transform3D & transform) {
in >> transform.mTranslation;
in >> transform.mScale;
in >> transform.mRotation;
transform.m_dirty = true;
return in;
}
QDataStream & Qtk::operator<<(QDataStream & out, const Qtk::Camera3D & camera) {
out << camera.getTransform();
return out;
}
QDataStream & Qtk::operator>>(QDataStream & in, Qtk::Camera3D & camera) {
in >> camera.mTransform;
return in;
}
#endif

View File

@@ -1,96 +0,0 @@
#ifndef QTK_QTKMESSAGELOGGER_H
#define QTK_QTKMESSAGELOGGER_H
#include "qtkapi.h"
#include <QDebug>
#include <QMessageLogger>
#include <Qt>
// #define qtkDebug Qtk::QtkMessageLogger::get().debug
// #define qtkInfo Qtk::QtkMessageLogger::get().info
// #define qtkWarning Qtk::QtkMessageLogger::get().warning
// #define qtkCritical Qtk::QtkMessageLogger::get().critical
// #define qtkFatal Qtk::QtkMessageLogger::get().fatal
#define qtkDebug \
Qtk::QtkMessageLogger( \
QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC) \
.logger() \
.debug
#define qtkInfo \
Qtk::QtkMessageLogger( \
QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC) \
.logger() \
.info
#define qtkWarning \
Qtk::QtkMessageLogger( \
QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC) \
.logger() \
.warning
#define qtkCritical \
Qtk::QtkMessageLogger( \
QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC) \
.logger() \
.critical
#define qtkFatal \
Qtk::QtkMessageLogger( \
QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC) \
.logger() \
.fatal
namespace Qtk {
class Transform3D;
class Camera3D;
class QTKAPI QtkDebug : public QDebug {
public:
QtkDebug operator<<(const Transform3D & transform);
};
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const Transform3D & transform);
QDebug operator<<(QDebug dbg, const Camera3D & camera);
#endif
#ifndef QT_NO_DATASTREAM
QDataStream & operator<<(QDataStream & out, const Transform3D & transform);
QDataStream & operator>>(QDataStream & in, Transform3D & transform);
QDataStream & operator<<(QDataStream & out, const Camera3D & camera);
QDataStream & operator>>(QDataStream & in, Camera3D & camera);
#endif
class QTKAPI QtkMessageLogger {
public:
QtkMessageLogger(const char * file, int line, const char * function) :
mQMessageLogger(file, line, function) {
qDebug();
}
// static QtkMessageLogger * get() {
// if(mQtkMessageLogger == Q_NULLPTR) {
// mQtkMessageLogger = new QtkMessageLogger();
// }
// return mQtkMessageLogger;
// }
// QtkDebug debug() const {}
[[nodiscard]] inline const QMessageLogger & logger() const {
return mQMessageLogger;
}
inline QtkDebug debug() const { return {}; };
static QtkMessageLogger * mQtkMessageLogger;
QMessageLogger mQMessageLogger;
};
} // namespace Qtk
#endif // QTK_QTKMESSAGELOGGER_H

View File

@@ -19,8 +19,8 @@ QMatrix4x4 Scene::mProjection;
******************************************************************************/ ******************************************************************************/
Scene::Scene() : mSceneName("Default Scene") { Scene::Scene() : mSceneName("Default Scene") {
mCamera.setTranslation({0.0f, 0.0f, 20.0f}); mCamera.getTransform().setTranslation(0.0f, 0.0f, 20.0f);
mCamera.setRotation({-5.0f, 0.0f, 1.0f, 0.0f}); mCamera.getTransform().setRotation(-5.0f, 0.0f, 1.0f, 0.0f);
} }
Scene::~Scene() { Scene::~Scene() {

View File

@@ -13,7 +13,6 @@
#include <QUrl> #include <QUrl>
#include <queue> #include <queue>
#include <unordered_map>
#include <utility> #include <utility>
#include "camera3d.h" #include "camera3d.h"
@@ -87,7 +86,7 @@ namespace Qtk {
void loadModel(const std::string & name, const std::string & path) { void loadModel(const std::string & name, const std::string & path) {
// Add the dropped model to the load queue. // Add the dropped model to the load queue.
// This is consumed during rendering of the scene if not empty. // This is consumed during rendering of the scene if not empty.
mModelLoadQueue.emplace(name, path); mModelLoadQueue.push({name, path});
} }
/************************************************************************* /*************************************************************************

View File

@@ -9,18 +9,19 @@
#include <QDebug> #include <QDebug>
#include <QImageReader> #include <QImageReader>
#include "app/qtkmainwindow.h"
#include "texture.h" #include "texture.h"
using namespace Qtk; using namespace Qtk;
QImage OpenGLTextureFactory::initImage( QImage * OpenGLTextureFactory::initImage(
const char * image, bool flipX, bool flipY) { const char * image, bool flipX, bool flipY) {
// Qt6 limits loaded images to 256MB by default // Qt6 limits loaded images to 256MB by default
QImageReader::setAllocationLimit(1024); QImageReader::setAllocationLimit(512);
auto loadedImage = QImage(image).mirrored(flipX, flipY); auto loadedImage = new QImage(QImage(image).mirrored(flipX, flipY));
if(loadedImage.isNull()) { if(loadedImage->isNull()) {
return defaultTexture(); qDebug() << "[Qtk::OpenGLTextureFactory] Error loading image: " << image
<< "\nSupported types: " << QImageReader::supportedImageFormats();
return Q_NULLPTR;
} }
return loadedImage; return loadedImage;
@@ -28,12 +29,13 @@ QImage OpenGLTextureFactory::initImage(
QOpenGLTexture * OpenGLTextureFactory::initTexture( QOpenGLTexture * OpenGLTextureFactory::initTexture(
const char * texture, bool flipX, bool flipY) { const char * texture, bool flipX, bool flipY) {
QImage image = initImage(texture, flipX, flipY); QImage * image = initImage(texture, flipX, flipY);
auto newTexture = new QOpenGLTexture(QOpenGLTexture::Target2D); auto newTexture = new QOpenGLTexture(QOpenGLTexture::Target2D);
newTexture->setData(image); newTexture->setData(*image);
newTexture->setWrapMode(QOpenGLTexture::Repeat); newTexture->setWrapMode(QOpenGLTexture::Repeat);
newTexture->setMinMagFilters( newTexture->setMinMagFilters(
QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear); QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
delete image;
return newTexture; return newTexture;
} }
@@ -69,7 +71,6 @@ QOpenGLTexture * OpenGLTextureFactory::initCubeMap(
QImage faceImage(faceTextures[i]); QImage faceImage(faceTextures[i]);
if(faceImage.isNull()) { if(faceImage.isNull()) {
qDebug() << "Error loading cube map image\n"; qDebug() << "Error loading cube map image\n";
faceImage = defaultTexture();
} }
faceImage = faceImage.convertToFormat(QImage::Format_RGBA8888); faceImage = faceImage.convertToFormat(QImage::Format_RGBA8888);

View File

@@ -74,9 +74,9 @@ namespace Qtk {
* Can be absolute or Qt resource path. * Can be absolute or Qt resource path.
* @param flipX If true the image will be flipped on X axis. * @param flipX If true the image will be flipped on X axis.
* @param flipY If true the image will be flipped on Y axis. * @param flipY If true the image will be flipped on Y axis.
* @return QImage object. * @return Pointer to an initialized QImage object.
*/ */
static QImage initImage( static QImage * initImage(
const char * image, bool flipX = false, bool flipY = false); const char * image, bool flipX = false, bool flipY = false);
/** /**
@@ -132,14 +132,6 @@ namespace Qtk {
const char * right, const char * top, const char * front, const char * right, const char * top, const char * front,
const char * left, const char * bottom, const char * back); const char * left, const char * bottom, const char * back);
/// The texture used in place of a missing texture.
static QImage defaultTexture() {
// Use plaster for default texture if image fails to load.
// This prevents segfaults when loading a texture that doesn't exist.
// TODO: Replace with a '?' texture to indicate missing texture.
return QImage(":/textures/plaster.png");
}
private: private:
// Private ctor to prevent creating instances of this class // Private ctor to prevent creating instances of this class
OpenGLTextureFactory() = default; OpenGLTextureFactory() = default;

View File

@@ -42,7 +42,6 @@ void Transform3D::rotate(const QQuaternion & dr) {
void Transform3D::setTranslation(const QVector3D & t) { void Transform3D::setTranslation(const QVector3D & t) {
m_dirty = true; m_dirty = true;
qtkDebug() << "Setting translation to " << t;
mTranslation = t; mTranslation = t;
} }
@@ -78,3 +77,45 @@ QVector3D Transform3D::getUp() const {
QVector3D Transform3D::getRight() const { QVector3D Transform3D::getRight() const {
return mRotation.rotatedVector(LocalRight); return mRotation.rotatedVector(LocalRight);
} }
/*******************************************************************************
* Private Methods
******************************************************************************/
namespace Qtk {
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const Transform3D & transform) {
dbg << "Transform3D\n{\n";
dbg << "Position: <" << transform.getTranslation().x() << ", "
<< transform.getTranslation().y() << ", "
<< transform.getTranslation().z() << ">\n";
dbg << "Scale: <" << transform.getScale().x() << ", "
<< transform.getScale().y() << ", " << transform.getScale().z()
<< ">\n";
dbg << "Rotation: <" << transform.getRotation().x() << ", "
<< transform.getRotation().y() << ", " << transform.getRotation().z()
<< " | " << transform.getRotation().scalar() << ">\n}";
return dbg;
}
#endif
#ifndef QT_NO_DATASTREAM
QDataStream & operator<<(QDataStream & out, const Transform3D & transform) {
out << transform.mTranslation;
out << transform.mScale;
out << transform.mRotation;
return out;
}
QDataStream & operator>>(QDataStream & in, Transform3D & transform) {
in >> transform.mTranslation;
in >> transform.mScale;
in >> transform.mRotation;
transform.m_dirty = true;
return in;
}
#endif
} // namespace Qtk

View File

@@ -116,12 +116,12 @@ namespace Qtk {
/** /**
* Apply rotation upon an axis represented by the 3D vector (x, y, z) * Apply rotation upon an axis represented by the 3D vector (x, y, z)
* *
* @param angle Angle to rotate.
* @param ax X axis to apply the rotation on. * @param ax X axis to apply the rotation on.
* @param ay Y axis to apply the rotation on. * @param ay Y axis to apply the rotation on.
* @param az Z axis to apply the rotation on. * @param az Z axis to apply the rotation on.
* @param angle Angle to rotate.
*/ */
inline void rotate(float ax, float ay, float az, float angle) { inline void rotate(float angle, float ax, float ay, float az) {
rotate(QQuaternion::fromAxisAndAngle(ax, ay, az, angle)); rotate(QQuaternion::fromAxisAndAngle(ax, ay, az, angle));
} }
@@ -178,12 +178,12 @@ namespace Qtk {
/** /**
* Sets a rotation upon an axis represented by the 3D vector (x, y, z) * Sets a rotation upon an axis represented by the 3D vector (x, y, z)
* *
* @param angle Angle to set rotation.
* @param ax X axis to set angle for. * @param ax X axis to set angle for.
* @param ay Y axis to set angle for. * @param ay Y axis to set angle for.
* @param az Z axis to set angle for. * @param az Z axis to set angle for.
* @param angle Angle to set rotation.
*/ */
inline void setRotation(float ax, float ay, float az, float angle) { inline void setRotation(float angle, float ax, float ay, float az) {
setRotation(QQuaternion::fromAxisAndAngle(ax, ay, az, angle)); setRotation(QQuaternion::fromAxisAndAngle(ax, ay, az, angle));
} }
@@ -249,10 +249,6 @@ namespace Qtk {
bool m_dirty; bool m_dirty;
/*************************************************************************
* Qt Streams
************************************************************************/
#ifndef QT_NO_DATASTREAM #ifndef QT_NO_DATASTREAM
friend QDataStream & operator<<( friend QDataStream & operator<<(
QDataStream & out, const Transform3D & transform); QDataStream & out, const Transform3D & transform);
@@ -260,6 +256,15 @@ namespace Qtk {
QDataStream & in, Transform3D & transform); QDataStream & in, Transform3D & transform);
#endif #endif
}; };
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const Transform3D & transform);
#endif
#ifndef QT_NO_DATASTREAM
QDataStream & operator<<(QDataStream & out, const Transform3D & transform);
QDataStream & operator>>(QDataStream & in, Transform3D & transform);
#endif
} // namespace Qtk } // namespace Qtk
Q_DECLARE_TYPEINFO(Qtk::Transform3D, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(Qtk::Transform3D, Q_MOVABLE_TYPE);