Compare commits

...

7 Commits

Author SHA1 Message Date
Shaun Reed 0f372f71f4 Add CI for assimp target build flag
+ Update README
2022-08-21 18:07:56 -04:00
Shaun Reed ad4d4636a4 Fix integration with Qt Creator
+ CMake build flag `QTK_UPDATE_SUBMODULES` to include Assimp as a git submodule
2022-08-21 18:03:04 -04:00
Shaun Reed 86b3f78368 Use configure_file to set QTK_RESOURCES 2022-08-21 18:03:04 -04:00
Shaun Reed 44d9092306 Use git submodule for assimp 2022-08-21 18:03:04 -04:00
Shaun Reed f3406ee749 Add assimp as external dependency 2022-08-21 18:03:04 -04:00
Shaun Reed 249a2b4446 Work on separating widget from main application
+ Thanks @OgreTransporter for help in #4!
+ Closes #4
2022-08-21 18:02:53 -04:00
Shaun Reed 432bf9919c Work on Windows CI 2022-08-06 15:18:55 -04:00
42 changed files with 1179 additions and 823 deletions

View File

@ -10,12 +10,14 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, macos-latest] os: [ubuntu-latest, windows-latest, macos-latest]
include: include:
- os: ubuntu-latest - os: ubuntu-latest
CMAKE_PARAMS: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.3.1/gcc_64/ cmake: -DCMAKE_PREFIX_PATH="/home/runner/work/qtk/Qt/6.3.1/gcc_64/"
- os: windows-latest
cmake: -DCMAKE_PREFIX_PATH="D:/a/qtk/qtk/Qt/6.3.1/mingw81_64/"
- os: macos-latest - os: macos-latest
CMAKE_PARAMS: -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.3.1/gcc_64/"
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
@ -26,11 +28,37 @@ jobs:
with: with:
version: '6.3.1' version: '6.3.1'
- name: Install Assimp Linux - name: Chocolatey Action
if: matrix.os == 'ubuntu-latest' if: matrix.os == 'windows-latest'
uses: crazy-max/ghaction-chocolatey@v2.0.0
with:
args: install pkgconfiglite
- name: Build Qtk
shell: bash shell: bash
run: | run: |
sudo apt install libassimp-dev -y cmake -S . -B build/ ${{ matrix.cmake }} && cmake --build build/ \
--target qtk-main
Build-Qtk-Assimp-Targets:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
include:
- os: ubuntu-latest
cmake: -DCMAKE_PREFIX_PATH="/home/runner/work/qtk/Qt/6.3.1/gcc_64/" -DQTK_UPDATE_SUBMODULES=OFF
- os: macos-latest
cmake: -DCMAKE_PREFIX_PATH="/home/runner/work/qtk/Qt/6.3.1/gcc_64/" -DASSIMP_NEW_INTERFACE=ON -DQTK_UPDATE_SUBMODULES=OFF
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- name: Install Qt
uses: jurplel/install-qt-action@v2
with:
version: '6.3.1'
- name: Install Assimp MacOS - name: Install Assimp MacOS
if: matrix.os == 'macos-latest' if: matrix.os == 'macos-latest'
@ -38,8 +66,14 @@ jobs:
run: | run: |
brew install assimp brew install assimp
- name: Install Assimp Ubuntu
if: matrix.os == 'ubuntu-latest'
shell: bash
run: |
sudo apt install libassimp-dev
- name: Build Qtk - name: Build Qtk
shell: bash shell: bash
run: | run: |
mkdir build && cd build cmake -S . -B build/ ${{ matrix.cmake }} && cmake --build build/ \
cmake .. ${{ matrix.CMAKE_PARAMS }} && cmake --build . --target qtk-main

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "extern/assimp/assimp"]
path = extern/assimp/assimp
url = https://github.com/assimp/assimp.git

View File

@ -3,7 +3,7 @@
## ## ## ##
## Project for working with OpenGL and Qt6 widgets ## ## Project for working with OpenGL and Qt6 widgets ##
################################################################################ ################################################################################
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.2)
project( project(
#[[NAME]] Qtk #[[NAME]] Qtk
@ -16,72 +16,212 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON) set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
# For CLion builds, point CMAKE_PREFIX_PATH to Qt6 install directory if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
list(APPEND CMAKE_PREFIX_PATH $ENV{HOME}/Code/Clones/Qt/6.3.1/gcc_64/) add_compile_options(/wd4131 /wd4127)
find_package(Qt6 COMPONENTS OpenGLWidgets)
if (NOT Qt6_FOUND)
message(SEND_ERROR "Unable to find Qt6 at CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}")
message(FATAL_ERROR "Specify path to Qt6 with `cmake -DCMAKE_PREFIX_PATH=/path/to/Qt/6.x.x/gcc_64 -S /path/to/qtk -B /path/to/qtk/build && cmake --build /path/to/qtk/build -j $(nprocs)`")
endif() endif()
message(STATUS "[Qtk] Compiling with ${CMAKE_CXX_COMPILER_ID}")
# Qtk build options
option(QTK_DEBUG "Enable debugger" ON)
message(STATUS "[Qtk] Compiling with QTK_DEBUG=${QTK_DEBUG}")
option(QTK_UPDATE_SUBMODULES "Update external project (assimp) submodule" ON)
message(
STATUS
"[Qtk] Compiling with QTK_UPDATE_SUBMODULES=${QTK_UPDATE_SUBMODULES}"
)
# Qt options
set(QT_DIR "$ENV{HOME}/Code/Clones/Qt/6.3.1/gcc_64/" CACHE PATH "Path to Qt6")
# Options for bringing your own assimp installation; Otherwise not needed
# + If assimp is available system-wide we can just set QTK_UPDATE_SUBMODULES OFF
option(ASSIMP_NEW_INTERFACE "Use the assimp::assimp interface (WIN / OSX)" OFF)
message(
STATUS
"[Qtk] Compiling with ASSIMP_NEW_INTERFACE=${ASSIMP_NEW_INTERFACE}"
)
################################################################################ ################################################################################
# External Libraries # External Libraries
################################################################################ ################################################################################
# https://github.com/assimp/assimp/commit/6ac8279977c3a54118551e549d77329497116f66 # For CLion builds, point CMAKE_PREFIX_PATH to Qt6 install directory
find_package(assimp REQUIRED) # + QtCreator will handle this for you if that is used instead
option(ASSIMP_NEW_INTERFACE "Use assimp::assimp as target instead of assimp" OFF) list(APPEND CMAKE_PREFIX_PATH "${QT_DIR}")
# Find Qt
find_package(Qt6 COMPONENTS OpenGLWidgets)
if (NOT Qt6_FOUND)
message(
SEND_ERROR "[Qtk] Error: Unable to find Qt6 at CMAKE_PREFIX_PATH: "
"${CMAKE_PREFIX_PATH}"
)
message(
FATAL_ERROR
"[Qtk] Error: Specify path to Qt6 with `cmake "
"-DCMAKE_PREFIX_PATH=/path/to/Qt/6.x.x/gcc_64 -S /path/to/qtk -B "
"/path/to/qtk/build && cmake --build /path/to/qtk/build -j $(nprocs)`"
)
endif()
if (QTK_UPDATE_SUBMODULES)
message(STATUS "[Qtk] Updating submodules...")
include("${CMAKE_SOURCE_DIR}/cmake/include/git_submodule.cmake")
submodule_update("${CMAKE_CURRENT_SOURCE_DIR}/extern/assimp/assimp/")
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/extern/assimp/assimp/")
else()
find_package(assimp REQUIRED)
endif()
################################################################################
# Qtk
################################################################################
set(
PUBLIC_HEADERS
src/qtkwidget.h
src/abstractscene.h
src/camera3d.h
src/mesh.h
src/meshrenderer.h
src/model.h
src/object.h
src/skybox.h
src/texture.h
src/transform3D.h
)
set(
SOURCE_FILES
src/qtkwidget.cpp
src/abstractscene.cpp
src/camera3d.cpp
src/input.cpp
src/input.h
src/mesh.cpp
src/meshrenderer.cpp
src/model.cpp
src/object.cpp
src/qtkapi.h
src/skybox.cpp
src/texture.cpp
src/transform3D.cpp
)
include(GenerateExportHeader) include(GenerateExportHeader)
add_library(qtk-widget STATIC ${PUBLIC_HEADERS} ${SOURCE_FILES})
target_include_directories(qtk-widget PRIVATE src/ app/)
set_target_properties(qtk-widget PROPERTIES
PUBLIC_HEADER "${PUBLIC_HEADERS}"
VERSION ${PROJECT_VERSION}
)
target_link_libraries(qtk-widget PUBLIC Qt6::OpenGLWidgets)
target_link_libraries(qtk-widget PUBLIC Qt6::Widgets)
if (QTK_UPDATE_SUBMODULES OR NOT ASSIMP_NEW_INTERFACE)
target_link_libraries(qtk-widget PUBLIC assimp)
elseif(ASSIMP_NEW_INTERFACE)
target_link_libraries(qtk-widget PUBLIC assimp::assimp)
endif()
if(QTK_DEBUG)
message(STATUS "[Qtk] Building with QTK_DEBUG=${QTK_DEBUG}")
target_compile_definitions(qtk-widget PUBLIC QTK_DEBUG)
endif()
if(WIN32)
find_package(OpenGL REQUIRED)
target_link_libraries(qtk-widget PUBLIC OpenGL::GL)
endif()
# Install files
install(TARGETS qtk-widget
# Associate qtk-widget target with qtk-export
EXPORT qtk-export
# <prefix>/bin on DLL systems and <prefix>/lib on non-dll systems
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib/static
RUNTIME DESTINATION bin
PUBLIC_HEADER DESTINATION include
)
# Install export
# qtkTargets.cmake will only be installed when one of the CONFIGURATIONS is installed
# + The generated import will only reference that qtk configuration
install(EXPORT qtk-export
FILE qtkTargets.cmake
CONFIGURATIONS Debug|Release
DESTINATION ${CMAKE_INSTALL_PREFIX}/cmake
)
################################################################################ ################################################################################
# Final Application # Final Application
################################################################################ ################################################################################
# Add our Qt resources.qrc file to our application set(QTK_RESOURCES "${CMAKE_SOURCE_DIR}/resources")
set(SOURCES app/main.cpp) configure_file(
qt6_add_big_resources(SOURCES resources.qrc) "${CMAKE_CURRENT_SOURCE_DIR}/src/qtkresources.h.in"
qt_add_executable(qtk ${SOURCES}) "${CMAKE_CURRENT_BINARY_DIR}/src/qtkresources.h"
@ONLY
set(SOURCES
src/mainwidget.cpp src/mainwidget.h
src/mainwindow.cpp src/mainwindow.h src/mainwindow.ui
src/input.cpp src/input.h
src/mesh.cpp src/mesh.h
src/texture.cpp src/texture.h
src/object.cpp src/object.h
src/meshrenderer.cpp src/meshrenderer.h
src/camera3d.cpp src/camera3d.h
src/skybox.cpp src/skybox.h
src/transform3D.cpp src/transform3D.h
src/model.cpp src/model.h
src/scene.cpp src/scene.h
src/resourcemanager.cpp src/resourcemanager.h
) )
qt_add_library(main-widget STATIC ${SOURCES})
target_include_directories(main-widget PUBLIC src/) # Add our Qt resources.qrc file to our application
if(ASSIMP_NEW_INTERFACE) set(QTK_APP_SOURCES app/main.cpp
target_link_libraries(main-widget PRIVATE assimp::assimp) app/examplescene.cpp app/examplescene.h
else() app/mainwindow.cpp app/mainwindow.h app/mainwindow.ui
target_link_libraries(main-widget PRIVATE assimp) app/resourcemanager.h
endif() src/qtkresources.h.in
target_link_libraries(main-widget PUBLIC Qt6::OpenGLWidgets) )
if(WIN32) qt6_add_big_resources(QTK_APP_SOURCES resources.qrc)
find_package(OpenGL REQUIRED)
target_link_libraries(main-widget PUBLIC OpenGL::GL)
endif()
target_link_libraries(qtk PUBLIC main-widget) qt_add_executable(qtk-main ${QTK_APP_SOURCES})
target_include_directories(qtk-main PRIVATE src/ app/)
# Link qtk executable to main main-widget library # Link qtk-main executable to main qtk-widget library
set_target_properties(qtk PROPERTIES target_link_libraries(qtk-main PUBLIC qtk-widget)
set_target_properties(qtk-main PROPERTIES
WIN32_EXECUTABLE TRUE WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
) )
install(TARGETS qtk-main
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
generate_export_header(main-widget) generate_export_header(qtk-widget)
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

@ -3,18 +3,18 @@
Practice project for learning about using OpenGL in Qt widget applications. Practice project for learning about using OpenGL in Qt widget applications.
Model loader using [Assimp](https://assimp.org/) within a Qt widget application. Model loader using [Assimp](https://assimp.org/) within a Qt widget application.
You can import your own models within `mainwdget.cpp`, inside the You can import your own models within `app/examplescene.cpp`, inside the
`MainWidget::initObjects()` function. I've commented throughout the code there `ExampleScene::init()` function. Rotations and translations
to explain which model or example I'm modifying. Rotations and translations happen in `ExampleScene::update()`.
happen in `MainWidget::update()`, to get textures loading on models look into
[material files](http://www.paulbourke.net/dataformats/mtl/) and see some
examples in the `resources/models/` directory. For more in-depth examples, see
`scene.h` and `scene.cpp`
Can be built with cmake manually or using To get textures loading on models look into [material files](http://www.paulbourke.net/dataformats/mtl/)
[Qt Creator](https://github.com/qt-creator/qt-creator). and see some examples in the `resources/models/` directory.
For the build to be successful, I've found through testing on VMs that the system requires around 6GB of RAM.
This is mostly due to the large .obj files that are built into the project using [Qt Resource System](https://doc.qt.io/qt-6/resources.html)
### Source Builds
Builds are configured for CLion or [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.
This project has been ported to Qt6, which is not yet available in Ubuntu apt repositories. This project has been ported to Qt6, 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.
@ -24,10 +24,32 @@ Once Qt6 is installed, to build and run `qtk` on Ubuntu -
```bash ```bash
sudo apt update -y && sudo apt install freeglut3-dev libassimp-dev cmake build-essential git sudo apt update -y && sudo apt install freeglut3-dev libassimp-dev cmake build-essential git
git clone https://gitlab.com/shaunrd0/qtk git clone https://gitlab.com/shaunrd0/qtk
cmake -DCMAKE_PREFIX_PATH=$HOME/Qt/6.3.1/gcc_64 -S qtk/ -B qtk/build/ && cmake --build qtk/build/ -j $(nprocs) cmake -DCMAKE_PREFIX_PATH=$HOME/Qt/6.3.1/gcc_64 -S qtk/ -B qtk/build/ && cmake --build qtk/build/ -j $(nproc --ignore=2) --target qtk-main
./qtk/build/qtk ./qtk/build/qtk-main
``` ```
By default, the build will initialize Assimp as a git submodule and build from source.
We can turn this off by setting the `-DQTK_UPDATE_SUBMODULES=OFF` flag when running CMake.
This will greatly increase build speed, but we will need to make sure Assimp is available either system-wide or using a custom `CMAKE_PREFIX_PATH`.
Using `-DQTK_UPDATE_SUBMODULES=ON` supports providing assimp on cross-platform builds (Windows / Mac / Linux) and may be easier to configure.
```bash
sudo apt update -y && sudo apt install freeglut3-dev libassimp-dev cmake build-essential git
git clone https://gitlab.com/shaunrd0/qtk
cmake -DQTK_UPDATE_SUBMODULES=OFF -DCMAKE_PREFIX_PATH=$HOME/Qt/6.3.1/gcc_64 -S qtk/ -B qtk/build/ && cmake --build qtk/build/ -j $(nproc --ignore=2) --target qtk-main
# We can also provide a path to assimp -
#cmake -DQTK_UPDATE_SUBMODULES=OFF -DCMAKE_PREFIX_PATH=$HOME/Qt/6.3.1/gcc_64;/path/to/assimp/ -S qtk/ -B qtk/build/ && cmake --build qtk/build/ -j $(nproc --ignore=2) --target qtk-main
./qtk/build/qtk-main
```
If you are building on **Windows / Mac** and bringing your own installation of Assimp, consider setting the `-DASSIMP_NEW_INTERFACE` build flag.
```bash
cmake -DASSIMP_NEW_INTERFACE=ON -DQTK_UPDATE_SUBMODULES=OFF -DCMAKE_PREFIX_PATH=$HOME/Qt/6.3.1/gcc_64;/path/to/assimp/ -S qtk/ -B qtk/build/ && cmake --build qtk/build/ -j $(nproc --ignore=2) --target qtk-main
```
### Controls
You can fly around the scene if you hold the right mouse button and use WASD. You can fly around the scene if you hold the right mouse button and use WASD.
If you see a small triangle floating by a model it represents the light source 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
@ -43,8 +65,30 @@ Spartan with normals -
![](resources/spartan-normals.png) ![](resources/spartan-normals.png)
## Model Artists
### QtkWidget in Qt Creator
The `QtkWidget` class is exported as a shared library for use in Qt Creator's design mode.
We can add more QtkWidgets to view and render the scene from multiple perspectives.
There is still some work to be done here, so there isn't a builtin way to add an additional view within the application.
![](resources/qtk-views.png)
After building Qtk, we can drag and drop an `OpenGL Widget` onto the `mainwindow.ui`.
Then right-click the new OpenGLWidget and `Promote To->QtkWidget` to add a second view.
![](resources/qtk-views-setup.png)
If we demote or delete all widgets in `mainwindow.ui` and rebuild the project, Qt Creator will drop `QtkWidget` from the list of possible promoted widgets.
Add an `OpenGL Widget` to the UI, right-click it and navigate to `Promote Widget...` and enter the information below.
![](resources/qtk-reference.png)
After you fill out the `New Promoted Class` form, click `Add` *and*`Promote`, then rebuild.
After following these steps Qt Creator will list `QtkWidget` as an option to promote `OpenGL Widgets` again.
## Model Artists
"Alien Hominid" (https://skfb.ly/onStx) by Nwilly_art is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/). "Alien Hominid" (https://skfb.ly/onStx) by Nwilly_art is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/).
@ -59,4 +103,3 @@ Modified (learnopengl.com) material assignment (Joey de Vries) for easier load i
"Terror-bird (NHMW-Geo 2012/0007/0001)" (https://skfb.ly/onAWy) by Natural History Museum Vienna is licensed under Creative Commons Attribution-NonCommercial (http://creativecommons.org/licenses/by-nc/4.0/). "Terror-bird (NHMW-Geo 2012/0007/0001)" (https://skfb.ly/onAWy) by Natural History Museum Vienna is licensed under Creative Commons Attribution-NonCommercial (http://creativecommons.org/licenses/by-nc/4.0/).
"Golden Lion Sitting OBJ Low Poly FREE" (https://skfb.ly/onZAH) by LordSamueliSolo is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/). "Golden Lion Sitting OBJ Low Poly FREE" (https://skfb.ly/onZAH) by LordSamueliSolo is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/).

View File

@ -6,32 +6,27 @@
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## ## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################*/ ##############################################################################*/
#include <abstractscene.h>
#include <camera3d.h> #include <camera3d.h>
#include <texture.h>
#include <meshrenderer.h> #include <meshrenderer.h>
#include <model.h> #include <model.h>
#include <resourcemanager.h> #include <resourcemanager.h>
#include <examplescene.h>
#include <texture.h>
#include <scene.h> using namespace Qtk;
Camera3D Scene::mCamera;
QMatrix4x4 Scene::mProjection;
/******************************************************************************* /*******************************************************************************
* Constructors, Destructors * Constructors, Destructors
******************************************************************************/ ******************************************************************************/
Scene::Scene() ExampleScene::ExampleScene()
{ {
mCamera.transform().setTranslation(0.0f, 0.0f, 20.0f); Camera().transform().setTranslation(0.0f, 0.0f, 20.0f);
mCamera.transform().setRotation(-5.0f, 0.0f, 1.0f, 0.0f); Camera().transform().setRotation(-5.0f, 0.0f, 1.0f, 0.0f);
init();
} }
Scene::~Scene() ExampleScene::~ExampleScene()
{ {
delete mTestPhong; delete mTestPhong;
delete mTestSpecular; delete mTestSpecular;
@ -39,6 +34,7 @@ Scene::~Scene()
delete mTestAmbient; delete mTestAmbient;
for (auto & mesh : mMeshes) delete mesh; for (auto & mesh : mMeshes) delete mesh;
for (auto & model : mModels) delete model; for (auto & model : mModels) delete model;
delete mSkybox;
} }
@ -46,10 +42,13 @@ Scene::~Scene()
* Public Member Functions * Public Member Functions
******************************************************************************/ ******************************************************************************/
void Scene::init() void ExampleScene::init()
{ {
Qtk::Skybox * sb = new Qtk::Skybox("Skybox");
setSkybox(sb);
// Initialize Phong example cube // Initialize Phong example cube
mTestPhong = new MeshRenderer("phong", Cube()); mTestPhong = new Qtk::MeshRenderer("phong", Qtk::Cube());
mTestPhong->mTransform.setTranslation(3.0f, 0.0f, -2.0f); mTestPhong->mTransform.setTranslation(3.0f, 0.0f, -2.0f);
mTestPhong->setShaders(":/solid-phong.vert", ":/solid-phong.frag"); mTestPhong->setShaders(":/solid-phong.vert", ":/solid-phong.frag");
mTestPhong->init(); mTestPhong->init();
@ -76,7 +75,7 @@ void Scene::init()
// Initialize Ambient example cube // Initialize Ambient example cube
mTestAmbient = new MeshRenderer("ambient", Cube()); mTestAmbient = new Qtk::MeshRenderer("ambient", Cube());
mTestAmbient->mTransform.setTranslation(7.0f, 0.0f, -2.0f); mTestAmbient->mTransform.setTranslation(7.0f, 0.0f, -2.0f);
mTestAmbient->setShaders(":/solid-ambient.vert", ":/solid-ambient.frag"); mTestAmbient->setShaders(":/solid-ambient.vert", ":/solid-ambient.frag");
mTestAmbient->init(); mTestAmbient->init();
@ -100,7 +99,7 @@ void Scene::init()
mTestAmbient->mProgram.release(); mTestAmbient->mProgram.release();
// Initialize Diffuse example cube // Initialize Diffuse example cube
mTestDiffuse = new MeshRenderer("diffuse", Cube()); mTestDiffuse = new Qtk::MeshRenderer("diffuse", Cube());
mTestDiffuse->mTransform.setTranslation(9.0f, 0.0f, -2.0f); mTestDiffuse->mTransform.setTranslation(9.0f, 0.0f, -2.0f);
mTestDiffuse->setShaders(":/solid-diffuse.vert", ":/solid-diffuse.frag"); mTestDiffuse->setShaders(":/solid-diffuse.vert", ":/solid-diffuse.frag");
mTestDiffuse->init(); mTestDiffuse->init();
@ -124,7 +123,7 @@ void Scene::init()
mTestDiffuse->mProgram.release(); mTestDiffuse->mProgram.release();
// Initialize Specular example cube // Initialize Specular example cube
mTestSpecular = new MeshRenderer("specular", Cube()); mTestSpecular = new Qtk::MeshRenderer("specular", Cube());
mTestSpecular->mTransform.setTranslation(11.0f, 0.0f, -2.0f); mTestSpecular->mTransform.setTranslation(11.0f, 0.0f, -2.0f);
mTestSpecular->setShaders(":/solid-specular.vert", ":/solid-specular.frag"); mTestSpecular->setShaders(":/solid-specular.vert", ":/solid-specular.frag");
mTestSpecular->init(); mTestSpecular->init();
@ -152,31 +151,31 @@ void Scene::init()
// //
// Model loading // Model loading
mModels.push_back(new Model("backpack", ":/models/backpack/backpack.obj")); mModels.push_back(new Qtk::Model("backpack", ":/models/backpack/backpack.obj"));
// Sometimes model textures need flipped in certain directions // Sometimes model textures need flipped in certain directions
mModels.back()->flipTexture("diffuse.jpg", false, true); mModels.back()->flipTexture("diffuse.jpg", false, true);
mModels.back()->mTransform.setTranslation(0.0f, 0.0f, -10.0f); mModels.back()->mTransform.setTranslation(0.0f, 0.0f, -10.0f);
mModels.push_back(new Model("bird", ":/models/bird/bird.obj")); mModels.push_back(new Qtk::Model("bird", ":/models/bird/bird.obj"));
mModels.back()->mTransform.setTranslation(2.0f, 2.0f, -10.0f); mModels.back()->mTransform.setTranslation(2.0f, 2.0f, -10.0f);
// Sometimes the models are very large // Sometimes the models are very large
mModels.back()->mTransform.scale(0.0025f); mModels.back()->mTransform.scale(0.0025f);
mModels.back()->mTransform.rotate(-110.0f, 0.0f, 1.0f, 0.0f); mModels.back()->mTransform.rotate(-110.0f, 0.0f, 1.0f, 0.0f);
mModels.push_back(new Model("lion", ":/models/lion/lion.obj")); mModels.push_back(new Qtk::Model("lion", ":/models/lion/lion.obj"));
mModels.back()->mTransform.setTranslation(-3.0f, -1.0f, -10.0f); mModels.back()->mTransform.setTranslation(-3.0f, -1.0f, -10.0f);
mModels.back()->mTransform.scale(0.15f); mModels.back()->mTransform.scale(0.15f);
mModels.push_back(new Model("alien", ":/models/alien-hominid/alien.obj")); mModels.push_back(new Qtk::Model("alien", ":/models/alien-hominid/alien.obj"));
mModels.back()->mTransform.setTranslation(2.0f, -1.0f, -5.0f); mModels.back()->mTransform.setTranslation(2.0f, -1.0f, -5.0f);
mModels.back()->mTransform.scale(0.15f); mModels.back()->mTransform.scale(0.15f);
mModels.push_back(new Model("scythe", ":/models/scythe/scythe.obj")); mModels.push_back(new Qtk::Model("scythe", ":/models/scythe/scythe.obj"));
mModels.back()->mTransform.setTranslation(-6.0f, 0.0f, -10.0f); mModels.back()->mTransform.setTranslation(-6.0f, 0.0f, -10.0f);
mModels.back()->mTransform.rotate(-90.0f, 1.0f, 0.0f, 0.0f); mModels.back()->mTransform.rotate(-90.0f, 1.0f, 0.0f, 0.0f);
mModels.back()->mTransform.rotate(90.0f, 0.0f, 1.0f, 0.0f); mModels.back()->mTransform.rotate(90.0f, 0.0f, 1.0f, 0.0f);
mModels.push_back(new Model("masterChief", ":/models/spartan/spartan.obj")); mModels.push_back(new Qtk::Model("masterChief", ":/models/spartan/spartan.obj"));
mModels.back()->mTransform.setTranslation(-1.5f, 0.5f, -2.0f); mModels.back()->mTransform.setTranslation(-1.5f, 0.5f, -2.0f);
@ -186,7 +185,7 @@ void Scene::init()
// Render an alien with specular // Render an alien with specular
// Test alien Model with phong lighting and specular mapping // Test alien Model with phong lighting and specular mapping
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("alienTestLight", Triangle(QTK_DRAW_ELEMENTS))); new Qtk::MeshRenderer("alienTestLight", Triangle(Qtk::QTK_DRAW_ELEMENTS)));
mMeshes.back()->mTransform.setTranslation(4.0f, 1.5f, 10.0f); mMeshes.back()->mTransform.setTranslation(4.0f, 1.5f, 10.0f);
mMeshes.back()->mTransform.scale(0.25f); mMeshes.back()->mTransform.scale(0.25f);
// This function changes values we have allocated in a buffer, so init() after // This function changes values we have allocated in a buffer, so init() after
@ -194,7 +193,7 @@ void Scene::init()
mMeshes.back()->init(); mMeshes.back()->init();
mModels.push_back( mModels.push_back(
new Model("alienTest", ":/models/alien-hominid/alien.obj", new Qtk::Model("alienTest", ":/models/alien-hominid/alien.obj",
":/model-specular.vert", ":/model-specular.frag") ":/model-specular.vert", ":/model-specular.frag")
); );
mModels.back()->mTransform.setTranslation(3.0f, -1.0f, 10.0f); mModels.back()->mTransform.setTranslation(3.0f, -1.0f, 10.0f);
@ -214,7 +213,7 @@ void Scene::init()
// Test spartan Model with phong lighting, specular and normal mapping // Test spartan Model with phong lighting, specular and normal mapping
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("spartanTestLight", Triangle(QTK_DRAW_ELEMENTS)) new Qtk::MeshRenderer("spartanTestLight", Triangle(QTK_DRAW_ELEMENTS))
); );
mMeshes.back()->mTransform.setTranslation(1.0f, 1.5f, 10.0f); mMeshes.back()->mTransform.setTranslation(1.0f, 1.5f, 10.0f);
mMeshes.back()->mTransform.scale(0.25f); mMeshes.back()->mTransform.scale(0.25f);
@ -223,7 +222,7 @@ void Scene::init()
mMeshes.back()->init(); mMeshes.back()->init();
mModels.push_back( mModels.push_back(
new Model("spartanTest", ":/models/spartan/spartan.obj", new Qtk::Model("spartanTest", ":/models/spartan/spartan.obj",
":/model-normals.vert", ":/model-normals.frag") ":/model-normals.vert", ":/model-normals.frag")
); );
mModels.back()->mTransform.setTranslation(0.0f, -1.0f, 10.0f); mModels.back()->mTransform.setTranslation(0.0f, -1.0f, 10.0f);
@ -242,7 +241,7 @@ void Scene::init()
// Test basic cube with phong.vert and phong.frag shaders // Test basic cube with phong.vert and phong.frag shaders
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("testLight", Triangle(QTK_DRAW_ELEMENTS))); new Qtk::MeshRenderer("testLight", Triangle(QTK_DRAW_ELEMENTS)));
mMeshes.back()->mTransform.setTranslation(5.0f, 1.25f, 10.0f); mMeshes.back()->mTransform.setTranslation(5.0f, 1.25f, 10.0f);
mMeshes.back()->mTransform.scale(0.25f); mMeshes.back()->mTransform.scale(0.25f);
mMeshes.back()->setDrawType(GL_LINE_LOOP); mMeshes.back()->setDrawType(GL_LINE_LOOP);
@ -251,7 +250,7 @@ void Scene::init()
mMeshes.back()->init(); mMeshes.back()->init();
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("testPhong", Cube(QTK_DRAW_ARRAYS))); new Qtk::MeshRenderer("testPhong", Cube(QTK_DRAW_ARRAYS)));
mMeshes.back()->mTransform.setTranslation(5.0f, 0.0f, 10.0f); mMeshes.back()->mTransform.setTranslation(5.0f, 0.0f, 10.0f);
mMeshes.back()->setShaders(":/phong.vert", ":/phong.frag"); mMeshes.back()->setShaders(":/phong.vert", ":/phong.frag");
mMeshes.back()->setColor(QVector3D(0.0f, 0.25f, 0.0f)); mMeshes.back()->setColor(QVector3D(0.0f, 0.25f, 0.0f));
@ -291,25 +290,25 @@ void Scene::init()
// Create simple shapes using MeshRenderer class and data in mesh.h // Create simple shapes using MeshRenderer class and data in mesh.h
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("rightTriangle", Triangle(QTK_DRAW_ELEMENTS))); new Qtk::MeshRenderer("rightTriangle", Triangle(QTK_DRAW_ELEMENTS)));
mMeshes.back()->mTransform.setTranslation(-5.0f, 0.0f, -2.0f); mMeshes.back()->mTransform.setTranslation(-5.0f, 0.0f, -2.0f);
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("centerCube", Cube(QTK_DRAW_ELEMENTS))); new Qtk::MeshRenderer("centerCube", Cube(QTK_DRAW_ELEMENTS)));
mMeshes.back()->mTransform.setTranslation(-7.0f, 0.0f, -2.0f); mMeshes.back()->mTransform.setTranslation(-7.0f, 0.0f, -2.0f);
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("leftTriangle", Triangle(QTK_DRAW_ELEMENTS))); new Qtk::MeshRenderer("leftTriangle", Triangle(QTK_DRAW_ELEMENTS)));
mMeshes.back()->mTransform.setTranslation(-9.0f, 0.0f, -2.0f); mMeshes.back()->mTransform.setTranslation(-9.0f, 0.0f, -2.0f);
mMeshes.back()->setDrawType(GL_LINE_LOOP); mMeshes.back()->setDrawType(GL_LINE_LOOP);
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("topTriangle", Triangle(QTK_DRAW_ELEMENTS))); new Qtk::MeshRenderer("topTriangle", Triangle(QTK_DRAW_ELEMENTS)));
mMeshes.back()->mTransform.setTranslation(-7.0f, 2.0f, -2.0f); mMeshes.back()->mTransform.setTranslation(-7.0f, 2.0f, -2.0f);
mMeshes.back()->mTransform.scale(0.25f); mMeshes.back()->mTransform.scale(0.25f);
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("bottomTriangle", Triangle(QTK_DRAW_ELEMENTS))); new Qtk::MeshRenderer("bottomTriangle", Triangle(QTK_DRAW_ELEMENTS)));
mMeshes.back()->mTransform.setTranslation(-7.0f, -2.0f, -2.0f); mMeshes.back()->mTransform.setTranslation(-7.0f, -2.0f, -2.0f);
mMeshes.back()->mTransform.scale(0.25f); mMeshes.back()->mTransform.scale(0.25f);
mMeshes.back()->setDrawType(GL_LINE_LOOP); mMeshes.back()->setDrawType(GL_LINE_LOOP);
@ -322,7 +321,7 @@ void Scene::init()
// RGB Normals cube to show normals are correct with QTK_DRAW_ARRAYS // RGB Normals cube to show normals are correct with QTK_DRAW_ARRAYS
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("rgbNormalsCubeArraysTest", Cube(QTK_DRAW_ARRAYS))); new Qtk::MeshRenderer("rgbNormalsCubeArraysTest", Cube(QTK_DRAW_ARRAYS)));
mMeshes.back()->mTransform.setTranslation(5.0f, 0.0f, 4.0f); mMeshes.back()->mTransform.setTranslation(5.0f, 0.0f, 4.0f);
mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag"); mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag");
mMeshes.back()->init(); mMeshes.back()->init();
@ -344,7 +343,7 @@ void Scene::init()
// RGB Normals cube to show normals are correct with QTK_DRAW_ELEMENTS_NORMALS // RGB Normals cube to show normals are correct with QTK_DRAW_ELEMENTS_NORMALS
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("rgbNormalsCubeElementsTest", Cube(QTK_DRAW_ELEMENTS_NORMALS))); new Qtk::MeshRenderer("rgbNormalsCubeElementsTest", Cube(QTK_DRAW_ELEMENTS_NORMALS)));
mMeshes.back()->mTransform.setTranslation(5.0f, 0.0f, 2.0f); mMeshes.back()->mTransform.setTranslation(5.0f, 0.0f, 2.0f);
mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag"); mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag");
mMeshes.back()->init(); mMeshes.back()->init();
@ -369,7 +368,7 @@ void Scene::init()
// + UVs required duplicating element position data from QTK_DRAW_ELEMENTS // + UVs required duplicating element position data from QTK_DRAW_ELEMENTS
// + This is because the same position must use different UV coordinates // + This is because the same position must use different UV coordinates
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("uvCubeArraysTest", Cube(QTK_DRAW_ARRAYS))); new Qtk::MeshRenderer("uvCubeArraysTest", Cube(QTK_DRAW_ARRAYS)));
mMeshes.back()->mTransform.setTranslation(-3.0f, 0.0f, -2.0f); mMeshes.back()->mTransform.setTranslation(-3.0f, 0.0f, -2.0f);
mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag"); mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag");
mMeshes.back()->init(); mMeshes.back()->init();
@ -397,7 +396,7 @@ void Scene::init()
// Test drawing a cube with texture coordinates using glDrawElements // Test drawing a cube with texture coordinates using glDrawElements
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("uvCubeElementsTest", Cube(QTK_DRAW_ELEMENTS_NORMALS))); new Qtk::MeshRenderer("uvCubeElementsTest", Cube(QTK_DRAW_ELEMENTS_NORMALS)));
mMeshes.back()->mTransform.setTranslation(-1.7f, 0.0f, -2.0f); mMeshes.back()->mTransform.setTranslation(-1.7f, 0.0f, -2.0f);
mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag"); mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag");
mMeshes.back()->init(); mMeshes.back()->init();
@ -423,7 +422,7 @@ void Scene::init()
// 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
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("testCubeMap", Cube(QTK_DRAW_ELEMENTS))); new Qtk::MeshRenderer("testCubeMap", Cube(QTK_DRAW_ELEMENTS)));
mMeshes.back()->mTransform.setTranslation(-3.0f, 1.0f, -2.0f); mMeshes.back()->mTransform.setTranslation(-3.0f, 1.0f, -2.0f);
mMeshes.back()->mTransform.setRotation(45.0f, 0.0f, 1.0f, 0.0f); mMeshes.back()->mTransform.setRotation(45.0f, 0.0f, 1.0f, 0.0f);
mMeshes.back()->setShaders(":/texture-cubemap.vert", ":/texture-cubemap.frag"); mMeshes.back()->setShaders(":/texture-cubemap.vert", ":/texture-cubemap.frag");
@ -450,7 +449,7 @@ void Scene::init()
// Create a cube with custom shaders // Create a cube with custom shaders
// + Apply RGB normals shader and spin the cube for a neat effect // + Apply RGB normals shader and spin the cube for a neat effect
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("rgbNormalsCube", Cube(QTK_DRAW_ARRAYS))); new Qtk::MeshRenderer("rgbNormalsCube", Cube(QTK_DRAW_ARRAYS)));
mMeshes.back()->mTransform.setTranslation(5.0f, 2.0f, -2.0f); mMeshes.back()->mTransform.setTranslation(5.0f, 2.0f, -2.0f);
mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag"); mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag");
mMeshes.back()->init(); mMeshes.back()->init();
@ -472,7 +471,7 @@ void Scene::init()
// RGB Normals triangle to show normals are correct with QTK_DRAW_ARRAYS // RGB Normals triangle to show normals are correct with QTK_DRAW_ARRAYS
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("rgbTriangleArraysTest", Triangle(QTK_DRAW_ARRAYS))); new Qtk::MeshRenderer("rgbTriangleArraysTest", Triangle(QTK_DRAW_ARRAYS)));
mMeshes.back()->mTransform.setTranslation(7.0f, 0.0f, 2.0f); mMeshes.back()->mTransform.setTranslation(7.0f, 0.0f, 2.0f);
mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag"); mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag");
mMeshes.back()->init(); mMeshes.back()->init();
@ -493,7 +492,7 @@ void Scene::init()
// RGB Normals triangle to show normals are correct with QTK_DRAW_ELEMENTS // RGB Normals triangle to show normals are correct with QTK_DRAW_ELEMENTS
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("rgbTriangleElementsTest", new Qtk::MeshRenderer("rgbTriangleElementsTest",
Triangle(QTK_DRAW_ELEMENTS_NORMALS))); Triangle(QTK_DRAW_ELEMENTS_NORMALS)));
mMeshes.back()->mTransform.setTranslation(7.0f, 0.0f, 4.0f); mMeshes.back()->mTransform.setTranslation(7.0f, 0.0f, 4.0f);
mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag"); mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag");
@ -515,7 +514,7 @@ void Scene::init()
// Test drawing triangle with glDrawArrays with texture coordinates // Test drawing triangle with glDrawArrays with texture coordinates
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("testTriangleArraysUV", Triangle(QTK_DRAW_ARRAYS))); new Qtk::MeshRenderer("testTriangleArraysUV", Triangle(QTK_DRAW_ARRAYS)));
mMeshes.back()->mTransform.setTranslation(-3.0f, 2.0f, -2.0f); mMeshes.back()->mTransform.setTranslation(-3.0f, 2.0f, -2.0f);
mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag"); mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag");
mMeshes.back()->init(); mMeshes.back()->init();
@ -543,7 +542,7 @@ void Scene::init()
// Test drawing triangle with glDrawElements with texture coordinates // Test drawing triangle with glDrawElements with texture coordinates
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("testTriangleElementsUV", new Qtk::MeshRenderer("testTriangleElementsUV",
Triangle(QTK_DRAW_ELEMENTS_NORMALS))); Triangle(QTK_DRAW_ELEMENTS_NORMALS)));
mMeshes.back()->mTransform.setTranslation(-2.5f, 0.0f, -1.0f); mMeshes.back()->mTransform.setTranslation(-2.5f, 0.0f, -1.0f);
mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag"); mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag");
@ -575,7 +574,7 @@ void Scene::init()
// Example of a cube with no lighting applied // Example of a cube with no lighting applied
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("noLight", Cube(QTK_DRAW_ELEMENTS))); new Qtk::MeshRenderer("noLight", Cube(QTK_DRAW_ELEMENTS)));
mMeshes.back()->mTransform.setTranslation(5.0f, 0.0f, -2.0f); mMeshes.back()->mTransform.setTranslation(5.0f, 0.0f, -2.0f);
mMeshes.back()->setShaders(":/solid-perspective.vert", mMeshes.back()->setShaders(":/solid-perspective.vert",
":/solid-perspective.frag"); ":/solid-perspective.frag");
@ -586,28 +585,24 @@ void Scene::init()
// Create objects that represent light sources for lighting examples // Create objects that represent light sources for lighting examples
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("phongLight", Triangle(QTK_DRAW_ELEMENTS))); new Qtk::MeshRenderer("phongLight", Triangle(QTK_DRAW_ELEMENTS)));
mMeshes.back()->mTransform.setTranslation(3.0f, 2.0f, -2.0f); mMeshes.back()->mTransform.setTranslation(3.0f, 2.0f, -2.0f);
mMeshes.back()->mTransform.scale(0.25f); mMeshes.back()->mTransform.scale(0.25f);
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("diffuseLight", Triangle(QTK_DRAW_ELEMENTS))); new Qtk::MeshRenderer("diffuseLight", Triangle(QTK_DRAW_ELEMENTS)));
mMeshes.back()->mTransform.setTranslation(9.0f, 2.0f, -2.0f); mMeshes.back()->mTransform.setTranslation(9.0f, 2.0f, -2.0f);
mMeshes.back()->mTransform.scale(0.25f); mMeshes.back()->mTransform.scale(0.25f);
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("specularLight", Triangle(QTK_DRAW_ELEMENTS))); new Qtk::MeshRenderer("specularLight", Triangle(QTK_DRAW_ELEMENTS)));
mMeshes.back()->mTransform.setTranslation(11.0f, 2.0f, -2.0f); mMeshes.back()->mTransform.setTranslation(11.0f, 2.0f, -2.0f);
mMeshes.back()->mTransform.scale(0.25f); mMeshes.back()->mTransform.scale(0.25f);
} }
void Scene::draw() void ExampleScene::draw()
{ {
mSkybox.draw(); Scene::draw();
for (auto & model : mModels) model->draw();
for (const auto &mesh : mMeshes) mesh->draw();
mTestPhong->mProgram.bind(); mTestPhong->mProgram.bind();
mTestPhong->setUniform("uModelInverseTransposed", mTestPhong->setUniform("uModelInverseTransposed",
@ -616,13 +611,13 @@ void Scene::draw()
"uLightPosition", "uLightPosition",
MeshRenderer::getInstance("phongLight")->mTransform.translation()); MeshRenderer::getInstance("phongLight")->mTransform.translation());
mTestPhong->setUniform("uCameraPosition", mTestPhong->setUniform("uCameraPosition",
Scene::Camera().transform().translation()); ExampleScene::Camera().transform().translation());
mTestPhong->mProgram.release(); mTestPhong->mProgram.release();
mTestPhong->draw(); mTestPhong->draw();
mTestAmbient->mProgram.bind(); mTestAmbient->mProgram.bind();
mTestAmbient->setUniform("uCameraPosition", mTestAmbient->setUniform("uCameraPosition",
Scene::Camera().transform().translation()); ExampleScene::Camera().transform().translation());
mTestAmbient->mProgram.release(); mTestAmbient->mProgram.release();
mTestAmbient->draw(); mTestAmbient->draw();
@ -632,7 +627,7 @@ void Scene::draw()
mTestDiffuse->setUniform( mTestDiffuse->setUniform(
"uLightPosition", "uLightPosition",
MeshRenderer::getInstance("diffuseLight")->mTransform.translation()); MeshRenderer::getInstance("diffuseLight")->mTransform.translation());
mTestDiffuse->setUniform("uCameraPosition", Scene::Camera().transform().translation()); mTestDiffuse->setUniform("uCameraPosition", ExampleScene::Camera().transform().translation());
mTestDiffuse->mProgram.release(); mTestDiffuse->mProgram.release();
mTestDiffuse->draw(); mTestDiffuse->draw();
@ -643,43 +638,43 @@ void Scene::draw()
mTestSpecular->setUniform( mTestSpecular->setUniform(
"uLightPosition", "uLightPosition",
MeshRenderer::getInstance("specularLight")->mTransform.translation()); MeshRenderer::getInstance("specularLight")->mTransform.translation());
mTestSpecular->setUniform("uCameraPosition", Scene::Camera().transform().translation()); mTestSpecular->setUniform("uCameraPosition", ExampleScene::Camera().transform().translation());
mTestSpecular->mProgram.release(); mTestSpecular->mProgram.release();
mTestSpecular->draw(); mTestSpecular->draw();
} }
void Scene::update() void ExampleScene::update()
{ {
auto position = MeshRenderer::getInstance("alienTestLight")->mTransform.translation(); auto position = MeshRenderer::getInstance("alienTestLight")->mTransform.translation();
Model::getInstance("alienTest")->setUniform( Model::getInstance("alienTest")->setUniform(
"uLight.position", position); "uLight.position", position);
Model::getInstance("alienTest")->setUniform( Model::getInstance("alienTest")->setUniform(
"uCameraPosition", Scene::Camera().transform().translation()); "uCameraPosition", ExampleScene::Camera().transform().translation());
auto posMatrix = Model::getInstance("alienTest")->mTransform.toMatrix(); auto posMatrix = Model::getInstance("alienTest")->mTransform.toMatrix();
Model::getInstance("alienTest")->setUniform( Model::getInstance("alienTest")->setUniform(
"uMVP.normalMatrix", posMatrix.normalMatrix()); "uMVP.normalMatrix", posMatrix.normalMatrix());
Model::getInstance("alienTest")->setUniform( Model::getInstance("alienTest")->setUniform(
"uMVP.model", posMatrix); "uMVP.model", posMatrix);
Model::getInstance("alienTest")->setUniform( Model::getInstance("alienTest")->setUniform(
"uMVP.view", Scene::Camera().toMatrix()); "uMVP.view", ExampleScene::Camera().toMatrix());
Model::getInstance("alienTest")->setUniform( Model::getInstance("alienTest")->setUniform(
"uMVP.projection", Scene::Projection()); "uMVP.projection", ExampleScene::Projection());
Model::getInstance("alienTest")->mTransform.rotate(0.75f, 0.0f, 1.0f, 0.0f); Model::getInstance("alienTest")->mTransform.rotate(0.75f, 0.0f, 1.0f, 0.0f);
position = MeshRenderer::getInstance("spartanTestLight")->mTransform.translation(); position = MeshRenderer::getInstance("spartanTestLight")->mTransform.translation();
Model::getInstance("spartanTest")->setUniform( Model::getInstance("spartanTest")->setUniform(
"uLight.position", position); "uLight.position", position);
Model::getInstance("spartanTest")->setUniform( Model::getInstance("spartanTest")->setUniform(
"uCameraPosition", Scene::Camera().transform().translation()); "uCameraPosition", ExampleScene::Camera().transform().translation());
posMatrix = Model::getInstance("spartanTest")->mTransform.toMatrix(); posMatrix = Model::getInstance("spartanTest")->mTransform.toMatrix();
Model::getInstance("spartanTest")->setUniform( Model::getInstance("spartanTest")->setUniform(
"uMVP.normalMatrix", posMatrix.normalMatrix()); "uMVP.normalMatrix", posMatrix.normalMatrix());
Model::getInstance("spartanTest")->setUniform( Model::getInstance("spartanTest")->setUniform(
"uMVP.model", posMatrix); "uMVP.model", posMatrix);
Model::getInstance("spartanTest")->setUniform( Model::getInstance("spartanTest")->setUniform(
"uMVP.view", Scene::Camera().toMatrix()); "uMVP.view", ExampleScene::Camera().toMatrix());
Model::getInstance("spartanTest")->setUniform( Model::getInstance("spartanTest")->setUniform(
"uMVP.projection", Scene::Projection()); "uMVP.projection", ExampleScene::Projection());
Model::getInstance("spartanTest")->mTransform.rotate(0.75f, 0.0f, 1.0f, 0.0f); Model::getInstance("spartanTest")->mTransform.rotate(0.75f, 0.0f, 1.0f, 0.0f);
@ -691,16 +686,16 @@ void Scene::update()
MeshRenderer::getInstance("testPhong")->setUniform( MeshRenderer::getInstance("testPhong")->setUniform(
"uLight.position", position); "uLight.position", position);
MeshRenderer::getInstance("testPhong")->setUniform( MeshRenderer::getInstance("testPhong")->setUniform(
"uCameraPosition", Scene::Camera().transform().translation()); "uCameraPosition", ExampleScene::Camera().transform().translation());
posMatrix = MeshRenderer::getInstance("testPhong")->mTransform.toMatrix(); posMatrix = MeshRenderer::getInstance("testPhong")->mTransform.toMatrix();
MeshRenderer::getInstance("testPhong")->setUniform( MeshRenderer::getInstance("testPhong")->setUniform(
"uMVP.normalMatrix", posMatrix.normalMatrix()); "uMVP.normalMatrix", posMatrix.normalMatrix());
MeshRenderer::getInstance("testPhong")->setUniform( MeshRenderer::getInstance("testPhong")->setUniform(
"uMVP.model", posMatrix); "uMVP.model", posMatrix);
MeshRenderer::getInstance("testPhong")->setUniform( MeshRenderer::getInstance("testPhong")->setUniform(
"uMVP.view", Scene::Camera().toMatrix()); "uMVP.view", ExampleScene::Camera().toMatrix());
MeshRenderer::getInstance("testPhong")->setUniform( MeshRenderer::getInstance("testPhong")->setUniform(
"uMVP.projection", Scene::Projection()); "uMVP.projection", ExampleScene::Projection());
MeshRenderer::getInstance("testPhong")->mProgram.release(); MeshRenderer::getInstance("testPhong")->mProgram.release();
// Rotate lighting example cubes // Rotate lighting example cubes

View File

@ -6,40 +6,31 @@
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## ## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################*/ ##############################################################################*/
#ifndef QTK_SCENE_H #ifndef QTK_EXAMPLE_SCENE_H
#define QTK_SCENE_H #define QTK_EXAMPLE_SCENE_H
#include <abstractscene.h>
#include <camera3d.h> #include <camera3d.h>
#include <skybox.h> #include <skybox.h>
#include <QMatrix4x4> #include <QMatrix4x4>
class MeshRenderer;
class Model;
class Scene { class ExampleScene : public Qtk::Scene {
public: public:
Scene(); ExampleScene();
~Scene(); ~ExampleScene();
void init(); virtual void init();
void draw(); virtual void draw() override;
void update(); virtual void update();
static Camera3D & Camera() { return mCamera;}
static QMatrix4x4 View() { return mCamera.toMatrix();}
static QMatrix4x4 & Projection() { return mProjection;}
private: private:
static Camera3D mCamera;
static QMatrix4x4 mProjection;
Skybox mSkybox; Qtk::MeshRenderer * mTestPhong;
MeshRenderer * mTestPhong; Qtk::MeshRenderer * mTestSpecular;
MeshRenderer * mTestSpecular; Qtk::MeshRenderer * mTestDiffuse;
MeshRenderer * mTestDiffuse; Qtk::MeshRenderer * mTestAmbient;
MeshRenderer * mTestAmbient;
std::vector<MeshRenderer *> mMeshes;
std::vector<Model *> mModels;
}; };
#endif // QTK_SCENE_H #endif // QTK_EXAMPLE_SCENE_H

View File

@ -9,7 +9,7 @@
#include <QApplication> #include <QApplication>
#include <QLabel> #include <QLabel>
#include <mainwidget.h> #include <qtkwidget.h>
#include <mainwindow.h> #include <mainwindow.h>

28
app/mainwindow.cpp Normal file
View File

@ -0,0 +1,28 @@
#include <mainwindow.h>
#include <qtkwidget.h>
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// For use in design mode using Qt Creator
// + We can use the `ui` member to access nested widgets by name
for (const auto widget : ui->qWidget->children()) {
auto qtkWidget = dynamic_cast<Qtk::QtkWidget*>(widget);
if (qtkWidget != nullptr) {
std::string key = qtkWidget->objectName().toStdString();
if (mScenes[key] == nullptr) {
mScenes[qtkWidget->objectName().toStdString()] = new ExampleScene();
}
qtkWidget->setScene(mScenes[qtkWidget->objectName().toStdString()]);
}
}
setWindowIcon(QIcon("../resources/icon.png"));
}
MainWindow::~MainWindow()
{
delete ui;
}

View File

@ -1,15 +1,19 @@
#ifndef MAINWINDOW_H #ifndef MAINWINDOW_H
#define MAINWINDOW_H #define MAINWINDOW_H
#include <unordered_map>
#include <QMainWindow> #include <QMainWindow>
#include "main-widget_export.h" #include "qtk-widget_export.h"
#include <examplescene.h>
namespace Ui { namespace Ui {
class MainWindow; class MainWindow;
} }
class MAIN_WIDGET_EXPORT MainWindow : public QMainWindow class QTK_WIDGET_EXPORT MainWindow : public QMainWindow
{ {
Q_OBJECT Q_OBJECT
@ -19,6 +23,7 @@ public:
private: private:
Ui::MainWindow *ui; Ui::MainWindow *ui;
std::unordered_map<std::string, Qtk::Scene*> mScenes;
}; };
#endif // MAINWINDOW_H #endif // MAINWINDOW_H

View File

@ -14,15 +14,25 @@
<string>Qtk - MainWindow</string> <string>Qtk - MainWindow</string>
</property> </property>
<widget class="QWidget" name="centralwidget"> <widget class="QWidget" name="centralwidget">
<widget class="MainWidget" name="openGLWidget"> <widget class="QWidget" name="qWidget" native="true">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>10</x> <x>0</x>
<y>10</y> <y>0</y>
<width>775</width> <width>801</width>
<height>550</height> <height>561</height>
</rect> </rect>
</property> </property>
<widget class="Qtk::QtkWidget" name="openGLWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>781</width>
<height>541</height>
</rect>
</property>
</widget>
</widget> </widget>
</widget> </widget>
<widget class="QMenuBar" name="menubar"> <widget class="QMenuBar" name="menubar">
@ -94,9 +104,9 @@
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>
<class>MainWidget</class> <class>Qtk::QtkWidget</class>
<extends>QOpenGLWidget</extends> <extends>QOpenGLWidget</extends>
<header>mainwidget.h</header> <header>qtkwidget.h</header>
</customwidget> </customwidget>
</customwidgets> </customwidgets>
<resources/> <resources/>

View File

@ -8,6 +8,8 @@
#include <string> #include <string>
#include <src/qtkresources.h>
#ifndef QTK_RESOURCEMANAGER_H #ifndef QTK_RESOURCEMANAGER_H
#define QTK_RESOURCEMANAGER_H #define QTK_RESOURCEMANAGER_H
@ -26,10 +28,8 @@ public:
*/ */
static std::string getPath(const std::string & path) { static std::string getPath(const std::string & path) {
// Only construct qtk resource path if in qrc format; else return it as-is // Only construct qtk resource path if in qrc format; else return it as-is
return path[0] == ':' ? resourcesDir + path.substr(2) : path; return path[0] == ':' ? QTK_RESOURCES + path.substr(1) : path;
} }
static std::string resourcesDir;
} RM; } RM;
#endif //QTK_RESOURCEMANAGER_H #endif //QTK_RESOURCEMANAGER_H

View File

@ -0,0 +1,32 @@
################################################################################
## Author: Shaun Reed | Contact: shaunrd0@gmail.com | URL: www.shaunreed.com ##
## ##
## CMake function to update git submodules ##
################################################################################
include_guard()
find_package(Git)
# _PATH: Path to git submodule location that we want to update
# + submodule_update(extern/assimp)
function(submodule_update _PATH)
if (NOT QTK_UPDATE_SUBMODULES)
return()
endif()
if (NOT GIT_FOUND)
message(FATAL_ERROR "[Qtk] Error: No git executable found")
endif()
execute_process(
COMMAND ${GIT_EXECUTABLE} submodule update --init --force "${_PATH}"
RESULT_VARIABLE result
)
if (NOT result EQUAL 0)
message(
FATAL_ERROR
"[Qtk] Error: Unable to update git submodule at ${_PATH}"
)
endif()
endfunction()

1
extern/assimp/assimp vendored Submodule

@ -0,0 +1 @@
Subproject commit bd64cc88dff17f118ecf32ebcbacaf566f6b6449

BIN
resources/qtk-reference.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

BIN
resources/qtk-views.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 KiB

48
src/abstractscene.cpp Normal file
View File

@ -0,0 +1,48 @@
/*##############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ##
## About: Classes for managing objects and data within a scene ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################*/
#include <abstractscene.h>
#include <camera3d.h>
#include <resourcemanager.h>
#include <texture.h>
using namespace Qtk;
Camera3D Scene::mCamera;
QMatrix4x4 Scene::mProjection;
/*******************************************************************************
* Constructors, Destructors
******************************************************************************/
Scene::Scene()
{
mCamera.transform().setTranslation(0.0f, 0.0f, 20.0f);
mCamera.transform().setRotation(-5.0f, 0.0f, 1.0f, 0.0f);
}
Scene::~Scene()
{
for (auto & mesh : mMeshes) delete mesh;
for (auto & model : mModels) delete model;
if (mSkybox != Q_NULLPTR) delete mSkybox;
}
void Scene::privDraw()
{
if (!mInit) {
initializeOpenGLFunctions();
init();
mInit = true;
}
if (mSkybox != Q_NULLPTR) mSkybox->draw();
for (auto & model : mModels) model->draw();
for (const auto & mesh : mMeshes) mesh->draw();
}

55
src/abstractscene.h Normal file
View File

@ -0,0 +1,55 @@
/*##############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ##
## About: Classes for managing objects and data within a scene ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################*/
#ifndef QTK_SCENE_H
#define QTK_SCENE_H
#include <camera3d.h>
#include <meshrenderer.h>
#include <model.h>
#include <skybox.h>
#include <QMatrix4x4>
namespace Qtk {
class Scene : protected QOpenGLFunctions {
friend class MainWidget;
public:
Scene();
~Scene();
virtual void init() = 0;
virtual void draw() { privDraw(); };
virtual void update() = 0;
static Camera3D & Camera() { return mCamera;}
static QMatrix4x4 View() { return mCamera.toMatrix();}
static QMatrix4x4 & Projection() { return mProjection;}
inline Skybox * getSkybox() {return mSkybox;}
inline void setSkybox(Skybox * skybox) {
mSkybox = skybox;
}
private:
static Camera3D mCamera;
static QMatrix4x4 mProjection;
bool mInit = false;
void privDraw();
protected:
Skybox * mSkybox;
std::vector<MeshRenderer *> mMeshes;
std::vector<Model *> mModels;
};
}
#endif // QTK_SCENE_H

View File

@ -8,6 +8,7 @@
#include <camera3d.h> #include <camera3d.h>
using namespace Qtk;
const QVector3D Camera3D::LocalForward(0.0f, 0.0f, -1.0f); const QVector3D Camera3D::LocalForward(0.0f, 0.0f, -1.0f);
const QVector3D Camera3D::LocalUp(0.0f, 1.0f, 0.0f); const QVector3D Camera3D::LocalUp(0.0f, 1.0f, 0.0f);

View File

@ -12,51 +12,53 @@
#include <QDebug> #include <QDebug>
#include <transform3D.h> #include <transform3D.h>
#include <qtkapi.h>
namespace Qtk {
class QTKAPI Camera3D {
public:
// Constants
static const QVector3D LocalForward;
static const QVector3D LocalUp;
static const QVector3D LocalRight;
class Camera3D { // Accessors
public: inline Transform3D & transform() { return mTransform;}
// Constants inline const QVector3D & translation() const
static const QVector3D LocalForward; { return mTransform.translation();}
static const QVector3D LocalUp; inline const QQuaternion & rotation() const
static const QVector3D LocalRight; { return mTransform.rotation();}
const QMatrix4x4 & toMatrix();
// Accessors // Queries
inline Transform3D & transform() { return mTransform;} inline QVector3D forward() const
inline const QVector3D & translation() const { return mTransform.rotation().rotatedVector(LocalForward);}
{ return mTransform.translation();} inline QVector3D right() const
inline const QQuaternion & rotation() const { return mTransform.rotation().rotatedVector(LocalRight);}
{ return mTransform.rotation();} inline QVector3D up() const
const QMatrix4x4 & toMatrix(); { return mTransform.rotation().rotatedVector(LocalUp);}
// Queries private:
inline QVector3D forward() const Transform3D mTransform;
{ return mTransform.rotation().rotatedVector(LocalForward);} QMatrix4x4 mWorld;
inline QVector3D right() const
{ return mTransform.rotation().rotatedVector(LocalRight);}
inline QVector3D up() const
{ return mTransform.rotation().rotatedVector(LocalUp);}
private:
Transform3D mTransform;
QMatrix4x4 mWorld;
#ifndef QT_NO_DATASTREAM #ifndef QT_NO_DATASTREAM
friend QDataStream & operator<<(QDataStream & out, Camera3D & transform); friend QDataStream & operator<<(QDataStream & out, Camera3D & transform);
friend QDataStream & operator>>(QDataStream & in, Camera3D & transform); friend QDataStream & operator>>(QDataStream & in, Camera3D & transform);
#endif #endif
}; };
Q_DECLARE_TYPEINFO(Camera3D, Q_MOVABLE_TYPE);
// Qt Streams // Qt Streams
#ifndef QT_NO_DATASTREAM #ifndef QT_NO_DATASTREAM
QDataStream & operator<<(QDataStream & out, const Camera3D & transform); QDataStream & operator<<(QDataStream & out, const Camera3D & transform);
QDataStream & operator>>(QDataStream & in, Camera3D & transform); QDataStream & operator>>(QDataStream & in, Camera3D & transform);
#endif #endif
#ifndef QT_NO_DEBUG_STREAM #ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const Camera3D & transform); QDebug operator<<(QDebug dbg, const Camera3D & transform);
#endif #endif
}
Q_DECLARE_TYPEINFO(Qtk::Camera3D, Q_MOVABLE_TYPE);
#endif // QTK_CAMERA3D_H #endif // QTK_CAMERA3D_H

View File

@ -13,6 +13,7 @@
#include <input.h> #include <input.h>
using namespace Qtk;
/******************************************************************************* /*******************************************************************************
* Static Helper Structs * Static Helper Structs

View File

@ -12,52 +12,54 @@
#include <QPoint> #include <QPoint>
#include <Qt> #include <Qt>
#include <qtkapi.h>
#include <qtkwidget.h>
class Input { namespace Qtk {
friend class MainWidget; class QTKAPI Input {
public: friend class Qtk::QtkWidget;
public:
// Possible key states
enum InputState
{
InputInvalid,
InputRegistered,
InputUnregistered,
InputTriggered,
InputPressed,
InputReleased
};
// Possible key states // State checking
enum InputState inline static bool keyTriggered(Qt::Key key)
{ { return keyState(key) == InputTriggered;}
InputInvalid, inline static bool keyPressed(Qt::Key key)
InputRegistered, { return keyState(key) == InputPressed;}
InputUnregistered, inline static bool keyReleased(Qt::Key key)
InputTriggered, { return keyState(key) == InputReleased;}
InputPressed, inline static bool buttonTriggered(Qt::MouseButton button)
InputReleased { return buttonState(button) == InputTriggered;}
inline static bool buttonPressed(Qt::MouseButton button)
{ return buttonState(button) == InputPressed;}
inline static bool buttonReleased(Qt::MouseButton button)
{ return buttonState(button) == InputReleased;}
// Implementation
static InputState keyState(Qt::Key key);
static InputState buttonState(Qt::MouseButton button);
static QPoint mousePosition();
static QPoint mouseDelta();
private:
// State updating
static void update();
static void registerKeyPress(int key);
static void registerKeyRelease(int key);
static void registerMousePress(Qt::MouseButton button);
static void registerMouseRelease(Qt::MouseButton button);
static void reset();
}; };
}
// State checking
inline static bool keyTriggered(Qt::Key key)
{ return keyState(key) == InputTriggered;}
inline static bool keyPressed(Qt::Key key)
{ return keyState(key) == InputPressed;}
inline static bool keyReleased(Qt::Key key)
{ return keyState(key) == InputReleased;}
inline static bool buttonTriggered(Qt::MouseButton button)
{ return buttonState(button) == InputTriggered;}
inline static bool buttonPressed(Qt::MouseButton button)
{ return buttonState(button) == InputPressed;}
inline static bool buttonReleased(Qt::MouseButton button)
{ return buttonState(button) == InputReleased;}
// Implementation
static InputState keyState(Qt::Key key);
static InputState buttonState(Qt::MouseButton button);
static QPoint mousePosition();
static QPoint mouseDelta();
private:
// State updating
static void update();
static void registerKeyPress(int key);
static void registerKeyRelease(int key);
static void registerMousePress(Qt::MouseButton button);
static void registerMouseRelease(Qt::MouseButton button);
static void reset();
};
#endif // QTOPENGL_INPUT_H #endif // QTOPENGL_INPUT_H

View File

@ -1,71 +0,0 @@
/*##############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ##
## About: Main window for Qt6 OpenGL widget application ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################*/
#ifndef QTK_MAINWIDGET_H
#define QTK_MAINWIDGET_H
#include <iostream>
#include <QMatrix4x4>
#include <QOpenGLDebugLogger>
#include <QOpenGLFunctions>
#include <QOpenGLWidget>
#define QTK_DEBUG
class MeshRenderer;
class Model;
class Object;
class Scene;
class Skybox;
class Texture;
class MainWidget : public QOpenGLWidget,
protected QOpenGLFunctions {
Q_OBJECT;
public:
// Constructors
MainWidget();
explicit MainWidget(QWidget *parent);
explicit MainWidget(const QSurfaceFormat &format);
~MainWidget() override;
private:
void teardownGL();
void initObjects();
public:
// Inherited virtual Members
void paintGL() override;
void initializeGL() override;
void resizeGL(int width, int height) override;
protected slots:
void update();
void messageLogged(const QOpenGLDebugMessage &msg);
// Protected Helpers
protected:
void keyPressEvent(QKeyEvent *event);
void keyReleaseEvent(QKeyEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
private:
// Private helpers
void initializeWidget();
void printContextInformation();
void updateCameraInput();
Scene * mScene;
Object * mObject;
QOpenGLDebugLogger * mDebugLogger;
};
#endif // QTK_MAINWIDGET_H

View File

@ -1,15 +0,0 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
setWindowIcon(QIcon("../resources/icon.png"));
}
MainWindow::~MainWindow()
{
delete ui;
}

View File

@ -8,6 +8,7 @@
#include <mesh.h> #include <mesh.h>
using namespace Qtk;
Cube::Cube(DrawMode mode) Cube::Cube(DrawMode mode)
{ {

View File

@ -12,25 +12,27 @@
#include <QVector2D> #include <QVector2D>
#include <QVector3D> #include <QVector3D>
#include <qtkapi.h>
#include <transform3D.h> #include <transform3D.h>
class MeshRenderer; namespace Qtk {
class Object; class MeshRenderer;
class Object;
// Define vertices for drawing a cube using two faces (8 vertex points) // Define vertices for drawing a cube using two faces (8 vertex points)
// Front Vertices // Front Vertices
#define VERTEX_FTR QVector3D( 0.5f, 0.5f, 0.5f) // 1 #define VERTEX_FTR QVector3D( 0.5f, 0.5f, 0.5f) // 1
#define VERTEX_FTL QVector3D(-0.5f, 0.5f, 0.5f) // 2 #define VERTEX_FTL QVector3D(-0.5f, 0.5f, 0.5f) // 2
#define VERTEX_FBL QVector3D(-0.5f, -0.5f, 0.5f) // 3 #define VERTEX_FBL QVector3D(-0.5f, -0.5f, 0.5f) // 3
#define VERTEX_FBR QVector3D( 0.5f, -0.5f, 0.5f) // 4 #define VERTEX_FBR QVector3D( 0.5f, -0.5f, 0.5f) // 4
// Back Vertices // Back Vertices
#define VERTEX_BTR QVector3D( 0.5f, 0.5f, -0.5f) // 5 #define VERTEX_BTR QVector3D( 0.5f, 0.5f, -0.5f) // 5
#define VERTEX_BTL QVector3D(-0.5f, 0.5f, -0.5f) // 6 #define VERTEX_BTL QVector3D(-0.5f, 0.5f, -0.5f) // 6
#define VERTEX_BBL QVector3D(-0.5f, -0.5f, -0.5f) // 7 #define VERTEX_BBL QVector3D(-0.5f, -0.5f, -0.5f) // 7
#define VERTEX_BBR QVector3D( 0.5f, -0.5f, -0.5f) // 8 #define VERTEX_BBR QVector3D( 0.5f, -0.5f, -0.5f) // 8
// Direction vectors // Direction vectors
#define VECTOR_UP QVector3D(0.0f, 1.0f, 0.0f) #define VECTOR_UP QVector3D(0.0f, 1.0f, 0.0f)
#define VECTOR_DOWN QVector3D(0.0f, -1.0f, 0.0f) #define VECTOR_DOWN QVector3D(0.0f, -1.0f, 0.0f)
#define VECTOR_LEFT QVector3D(-1.0f, 0.0f, 0.0f) #define VECTOR_LEFT QVector3D(-1.0f, 0.0f, 0.0f)
@ -38,25 +40,25 @@ class Object;
#define VECTOR_FORWARD QVector3D(0.0f, 0.0f, 1.0f) #define VECTOR_FORWARD QVector3D(0.0f, 0.0f, 1.0f)
#define VECTOR_BACK QVector3D(0.0f, 0.0f, -1.0f) #define VECTOR_BACK QVector3D(0.0f, 0.0f, -1.0f)
// Identity and zero vectors // Identity and zero vectors
#define VECTOR_ONE QVector3D(1.0f, 1.0f, 1.0f) #define VECTOR_ONE QVector3D(1.0f, 1.0f, 1.0f)
#define VECTOR_ZERO QVector3D(0.0f, 0.0f, 0.0f) #define VECTOR_ZERO QVector3D(0.0f, 0.0f, 0.0f)
// A series of direction vectors to represent cube face normal // A series of direction vectors to represent cube face normal
#define FACE_TOP VECTOR_UP, VECTOR_UP, VECTOR_UP, \ #define FACE_TOP VECTOR_UP, VECTOR_UP, VECTOR_UP, \
VECTOR_UP, VECTOR_UP, VECTOR_UP VECTOR_UP, VECTOR_UP, VECTOR_UP
#define FACE_BOTTOM VECTOR_DOWN, VECTOR_DOWN, VECTOR_DOWN, \ #define FACE_BOTTOM VECTOR_DOWN, VECTOR_DOWN, VECTOR_DOWN, \
VECTOR_DOWN, VECTOR_DOWN, VECTOR_DOWN VECTOR_DOWN, VECTOR_DOWN, VECTOR_DOWN
#define FACE_LEFT VECTOR_LEFT, VECTOR_LEFT, VECTOR_LEFT, \ #define FACE_LEFT VECTOR_LEFT, VECTOR_LEFT, VECTOR_LEFT, \
VECTOR_LEFT, VECTOR_LEFT, VECTOR_LEFT VECTOR_LEFT, VECTOR_LEFT, VECTOR_LEFT
#define FACE_RIGHT VECTOR_RIGHT, VECTOR_RIGHT, VECTOR_RIGHT, \ #define FACE_RIGHT VECTOR_RIGHT, VECTOR_RIGHT, VECTOR_RIGHT, \
VECTOR_RIGHT, VECTOR_RIGHT, VECTOR_RIGHT VECTOR_RIGHT, VECTOR_RIGHT, VECTOR_RIGHT
#define FACE_FRONT VECTOR_FORWARD, VECTOR_FORWARD, VECTOR_FORWARD, \ #define FACE_FRONT VECTOR_FORWARD, VECTOR_FORWARD, VECTOR_FORWARD, \
VECTOR_FORWARD, VECTOR_FORWARD, VECTOR_FORWARD VECTOR_FORWARD, VECTOR_FORWARD, VECTOR_FORWARD
#define FACE_BACK VECTOR_BACK, VECTOR_BACK, VECTOR_BACK, \ #define FACE_BACK VECTOR_BACK, VECTOR_BACK, VECTOR_BACK, \
VECTOR_BACK, VECTOR_BACK, VECTOR_BACK VECTOR_BACK, VECTOR_BACK, VECTOR_BACK
// Colors using QVector3Ds as RGB values // Colors using QVector3Ds as RGB values
#define WHITE VECTOR_ONE #define WHITE VECTOR_ONE
#define BLACK VECTOR_ZERO #define BLACK VECTOR_ZERO
#define RED QVector3D(1.0f, 0.0f, 0.0f) #define RED QVector3D(1.0f, 0.0f, 0.0f)
@ -71,62 +73,62 @@ class Object;
#define UV_RIGHT QVector2D(0.0f, 1.0f) #define UV_RIGHT QVector2D(0.0f, 1.0f)
#define UV_CORNER QVector2D(1.0f, 1.0f) #define UV_CORNER QVector2D(1.0f, 1.0f)
typedef std::vector<QVector3D> Vertices;
typedef std::vector<QVector3D> Colors;
typedef std::vector<GLuint> Indices;
typedef std::vector<QVector2D> TexCoords;
typedef std::vector<QVector3D> Normals;
typedef std::vector<QVector3D> Vertices; enum DrawMode { QTK_DRAW_ARRAYS, QTK_DRAW_ELEMENTS, QTK_DRAW_ELEMENTS_NORMALS };
typedef std::vector<QVector3D> Colors;
typedef std::vector<GLuint> Indices;
typedef std::vector<QVector2D> TexCoords;
typedef std::vector<QVector3D> Normals;
enum DrawMode { QTK_DRAW_ARRAYS, QTK_DRAW_ELEMENTS, QTK_DRAW_ELEMENTS_NORMALS }; struct QTKAPI ShapeBase {
ShapeBase(DrawMode mode=QTK_DRAW_ARRAYS, Vertices v={},Indices i={}, Colors c={},
TexCoords t={}, Normals n={})
: mVertices(v), mColors(c), mIndices(i), mTexCoords(t), mNormals(n)
{}
struct ShapeBase { inline const Vertices & vertices() const { return mVertices;}
ShapeBase(DrawMode mode=QTK_DRAW_ARRAYS, Vertices v={},Indices i={}, Colors c={}, inline const Indices & indices() const { return mIndices;}
TexCoords t={}, Normals n={}) inline const Colors & colors() const { return mColors;}
: mVertices(v), mColors(c), mIndices(i), mTexCoords(t), mNormals(n) inline const TexCoords & texCoords() const { return mTexCoords;}
{} inline const Normals & normals() const { return mNormals;}
inline const Vertices & vertices() const { return mVertices;} protected:
inline const Indices & indices() const { return mIndices;} DrawMode mDrawMode;
inline const Colors & colors() const { return mColors;}
inline const TexCoords & texCoords() const { return mTexCoords;}
inline const Normals & normals() const { return mNormals;}
protected: Vertices mVertices;
DrawMode mDrawMode; Colors mColors;
Indices mIndices;
TexCoords mTexCoords;
Normals mNormals;
};
Vertices mVertices; struct Shape : public ShapeBase {
Colors mColors; friend MeshRenderer;
Indices mIndices; friend Object;
TexCoords mTexCoords; Shape () {}
Normals mNormals; Shape(const ShapeBase & rhs) : ShapeBase(rhs) {}
};
struct Shape : public ShapeBase { virtual inline void setVertices(const Vertices & value) {mVertices = value;}
friend MeshRenderer; virtual inline void setIndices(const Indices & value) {mIndices = value;}
friend Object; virtual inline void setColors(const Colors & value) {mColors = value;}
Shape () {} virtual inline void setTexCoords(const TexCoords & value) {mTexCoords = value;}
Shape(const ShapeBase & rhs) : ShapeBase(rhs) {} virtual inline void setNormals(const Normals & value) {mNormals = value;}
virtual inline void setShape(const Shape & value) { *this = value;}
virtual inline void setVertices(const Vertices & value) {mVertices = value;} };
virtual inline void setIndices(const Indices & value) {mIndices = value;}
virtual inline void setColors(const Colors & value) {mColors = value;}
virtual inline void setTexCoords(const TexCoords & value) {mTexCoords = value;}
virtual inline void setNormals(const Normals & value) {mNormals = value;}
virtual inline void setShape(const Shape & value) { *this = value;}
};
// Primitives inherit from ShapeBase, does not allow setting of shape values // Primitives inherit from ShapeBase, does not allow setting of shape values
class Mesh { class QTKAPI Mesh {
}; };
struct Cube : public ShapeBase { struct QTKAPI Cube : public ShapeBase {
Cube(DrawMode mode=QTK_DRAW_ARRAYS); Cube(DrawMode mode=QTK_DRAW_ARRAYS);
}; };
struct Triangle : public ShapeBase { struct QTKAPI Triangle : public ShapeBase {
Triangle(DrawMode mode=QTK_DRAW_ARRAYS); Triangle(DrawMode mode=QTK_DRAW_ARRAYS);
}; };
}
#endif // QTK_MESH_H #endif // QTK_MESH_H

View File

@ -8,14 +8,14 @@
#include <QImageReader> #include <QImageReader>
#include <scene.h> #include <abstractscene.h>
#include <meshrenderer.h>
#include <texture.h> #include <texture.h>
#include <meshrenderer.h> using namespace Qtk;
// Static QHash that holds all MeshRenderer instances using their mName as keys // Static QHash that holds all MeshRenderer instances using their mName as keys
MeshRenderer::MeshManager MeshRenderer::sInstances; Qtk::MeshRenderer::MeshManager Qtk::MeshRenderer::sInstances;
MeshRenderer::MeshRenderer(const char * name, const ShapeBase & shape) MeshRenderer::MeshRenderer(const char * name, const ShapeBase & shape)
: Object(name, shape), mVertexShader(":/multi-color.vert"), : Object(name, shape), mVertexShader(":/multi-color.vert"),

View File

@ -10,68 +10,71 @@
#include <mesh.h> #include <mesh.h>
#include <object.h> #include <object.h>
#include <qtkapi.h>
class MeshRenderer : public Object { namespace Qtk {
public: class QTKAPI MeshRenderer : public Object {
// Delegate constructors public:
MeshRenderer(const char * name, Vertices vertices, Indices indices, // Delegate constructors
DrawMode mode=QTK_DRAW_ARRAYS) MeshRenderer(const char * name, Vertices vertices, Indices indices,
: MeshRenderer(name, ShapeBase(mode, vertices, indices)) DrawMode mode=QTK_DRAW_ARRAYS)
{} : MeshRenderer(name, ShapeBase(mode, vertices, indices))
MeshRenderer(const char * name) {}
: MeshRenderer(name, Cube(QTK_DRAW_ELEMENTS)) MeshRenderer(const char * name)
{} : MeshRenderer(name, Cube(QTK_DRAW_ELEMENTS))
// Constructor {}
MeshRenderer(const char * name, const ShapeBase &shape); // Constructor
~MeshRenderer(); MeshRenderer(const char * name, const ShapeBase &shape);
~MeshRenderer();
// Retrieve a mesh by name stored within a static QHash // Retrieve a mesh by name stored within a static QHash
static MeshRenderer * getInstance(const QString & name); static MeshRenderer * getInstance(const QString & name);
void init(); void init();
void draw(); void draw();
// Draw types like GL_TRIANGLES, GL_POINTS, GL_LINES, etc // Draw types like GL_TRIANGLES, GL_POINTS, GL_LINES, etc
void setDrawType(int drawType) { mDrawType = drawType;} void setDrawType(int drawType) { mDrawType = drawType;}
// Shader settings // Shader settings
inline void setShaderVertex(const std::string & vert) { mVertexShader = vert;} inline void setShaderVertex(const std::string & vert) { mVertexShader = vert;}
inline void setShaderFragment(const std::string & frag) inline void setShaderFragment(const std::string & frag)
{ mFragmentShader = frag;} { mFragmentShader = frag;}
void setShaders(const std::string & vert, const std::string & frag); void setShaders(const std::string & vert, const std::string & frag);
template <typename T> template <typename T>
inline void setUniform(int location, T value) inline void setUniform(int location, T value)
{ mProgram.setUniformValue(location, value);} { mProgram.setUniformValue(location, value);}
template <typename T> template <typename T>
inline void setUniform(const char * location, T value) inline void setUniform(const char * location, T value)
{ mProgram.setUniformValue(location, value);} { mProgram.setUniformValue(location, value);}
// Set MVP matrix using this Object's transform // Set MVP matrix using this Object's transform
// + View and projection provided by MainWidget static members // + View and projection provided by MainWidget static members
void setUniformMVP(const char * model="uModel", const char * view="uView", void setUniformMVP(const char * model="uModel", const char * view="uView",
const char * projection="uProjection"); const char * projection="uProjection");
// Sets the texture to the image at the given path // Sets the texture to the image at the given path
// + Sets mHasTexture to enable texture binding in draw() // + Sets mHasTexture to enable texture binding in draw()
void setTexture(const char * path); void setTexture(const char * path);
void setTexture(QOpenGLTexture * texture); void setTexture(QOpenGLTexture * texture);
// These functions modify data stored in a VBO // These functions modify data stored in a VBO
// + After calling them, the VBO will need to be reallocated // + After calling them, the VBO will need to be reallocated
void setShape(const Shape & value) override; void setShape(const Shape & value) override;
void setColor(const QVector3D & color); void setColor(const QVector3D & color);
// Static QHash of all mesh objects within the scene // Static QHash of all mesh objects within the scene
typedef QHash<QString, MeshRenderer *> MeshManager; typedef QHash<QString, MeshRenderer *> MeshManager;
private: private:
static MeshManager sInstances; static MeshManager sInstances;
int mDrawType; int mDrawType;
bool mHasTexture; bool mHasTexture;
std::string mVertexShader, mFragmentShader; std::string mVertexShader, mFragmentShader;
}; };
}
#endif // QTK_MESHRENDERER_H #endif // QTK_MESHRENDERER_H

View File

@ -9,12 +9,12 @@
#include <QFileInfo> #include <QFileInfo>
#include <scene.h> #include <abstractscene.h>
#include <texture.h>
#include <resourcemanager.h>
#include <model.h> #include <model.h>
#include <resourcemanager.h>
#include <texture.h>
using namespace Qtk;
Model::ModelManager Model::mManager; Model::ModelManager Model::mManager;

View File

@ -16,7 +16,6 @@
#include <QOpenGLShaderProgram> #include <QOpenGLShaderProgram>
#include <QOpenGLTexture> #include <QOpenGLTexture>
#include <QOpenGLVertexArrayObject> #include <QOpenGLVertexArrayObject>
#include <QOpenGLFunctions>
// Assimp // Assimp
#include <assimp/Importer.hpp> #include <assimp/Importer.hpp>
@ -24,117 +23,119 @@
#include <assimp/scene.h> #include <assimp/scene.h>
// QTK // QTK
#include <qtkapi.h>
#include <transform3D.h> #include <transform3D.h>
namespace Qtk {
struct QTKAPI ModelVertex {
QVector3D mPosition;
QVector3D mNormal;
QVector3D mTangent;
QVector3D mBitangent;
QVector2D mTextureCoord;
};
struct ModelVertex { struct QTKAPI ModelTexture {
QVector3D mPosition; GLuint mID;
QVector3D mNormal; QOpenGLTexture * mTexture;
QVector3D mTangent; std::string mType;
QVector3D mBitangent; std::string mPath;
QVector2D mTextureCoord; };
};
struct ModelTexture { class Model;
GLuint mID;
QOpenGLTexture * mTexture;
std::string mType;
std::string mPath;
};
class Model; class QTKAPI ModelMesh : protected QOpenGLFunctions {
public:
friend Model;
typedef std::vector<ModelVertex> Vertices;
typedef std::vector<GLuint> Indices;
typedef std::vector<ModelTexture> Textures;
class ModelMesh : protected QOpenGLFunctions { // Constructors, Destructors
public: ModelMesh(Vertices vertices, Indices indices, Textures textures,
friend Model; const char * vertexShader=":/model-basic.vert",
typedef std::vector<ModelVertex> Vertices; const char * fragmentShader=":/model-basic.frag")
typedef std::vector<GLuint> Indices; : mProgram(new QOpenGLShaderProgram),
typedef std::vector<ModelTexture> Textures;
// Constructors, Destructors
ModelMesh(Vertices vertices, Indices indices, Textures textures,
const char * vertexShader=":/model-basic.vert",
const char * fragmentShader=":/model-basic.frag")
: mProgram(new QOpenGLShaderProgram),
mVAO(new QOpenGLVertexArrayObject), mVAO(new QOpenGLVertexArrayObject),
mVBO(new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer)), mVBO(new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer)),
mEBO(new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer)), mEBO(new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer)),
mVertices(std::move(vertices)), mVertices(std::move(vertices)),
mIndices(std::move(indices)), mIndices(std::move(indices)),
mTextures(std::move(textures)) mTextures(std::move(textures))
{ initMesh(vertexShader, fragmentShader);} { initMesh(vertexShader, fragmentShader);}
~ModelMesh() {} ~ModelMesh() {}
private: private:
void initMesh(const char * vert, const char * frag); void initMesh(const char * vert, const char * frag);
// ModelMesh Private Members // ModelMesh Private Members
QOpenGLBuffer * mVBO, * mEBO; QOpenGLBuffer * mVBO, * mEBO;
QOpenGLVertexArrayObject * mVAO; QOpenGLVertexArrayObject * mVAO;
QOpenGLShaderProgram * mProgram; QOpenGLShaderProgram * mProgram;
public: public:
inline void draw() { draw(*mProgram);} inline void draw() { draw(*mProgram);}
void draw(QOpenGLShaderProgram & shader); void draw(QOpenGLShaderProgram & shader);
// ModelMesh Public Members // ModelMesh Public Members
Vertices mVertices; Vertices mVertices;
Indices mIndices; Indices mIndices;
Textures mTextures; Textures mTextures;
Transform3D mTransform; Transform3D mTransform;
}; };
class Model : public QObject { class QTKAPI Model : public QObject {
Q_OBJECT Q_OBJECT
public: public:
inline Model(const char * name, const char * path, inline Model(const char * name, const char * path,
const char * vertexShader=":/model-basic.vert", const char * vertexShader=":/model-basic.vert",
const char * fragmentShader=":/model-basic.frag") const char * fragmentShader=":/model-basic.frag")
: mName(name), mVertexShader(vertexShader), : mName(name), mVertexShader(vertexShader),
mFragmentShader(fragmentShader) mFragmentShader(fragmentShader)
{ loadModel(path);} { loadModel(path);}
inline ~Model() { mManager.remove(mName);} inline ~Model() { mManager.remove(mName);}
void draw(); void draw();
void draw(QOpenGLShaderProgram & shader); void draw(QOpenGLShaderProgram & shader);
void flipTexture(const std::string & fileName, void flipTexture(const std::string & fileName,
bool flipX=false, bool flipY=true); bool flipX=false, bool flipY=true);
template <typename T> template <typename T>
void setUniform(const char * location, T value) void setUniform(const char * location, T value)
{ {
for (auto & mesh : mMeshes) { for (auto & mesh : mMeshes) {
mesh.mProgram->bind(); mesh.mProgram->bind();
mesh.mProgram->setUniformValue(location, value); mesh.mProgram->setUniformValue(location, value);
mesh.mProgram->release(); mesh.mProgram->release();
}
} }
}
Transform3D mTransform; Transform3D mTransform;
static Model * getInstance(const char * name); static Model * getInstance(const char * name);
typedef QHash<QString, Model *> ModelManager; typedef QHash<QString, Model *> ModelManager;
private: private:
static ModelManager mManager; static ModelManager mManager;
void loadModel(const std::string & path); void loadModel(const std::string & path);
void processNode(aiNode * node, const aiScene * scene); void processNode(aiNode * node, const aiScene * scene);
ModelMesh processMesh(aiMesh * mesh, const aiScene * scene); ModelMesh processMesh(aiMesh * mesh, const aiScene * scene);
ModelMesh::Textures loadMaterialTextures(aiMaterial * mat, aiTextureType type, ModelMesh::Textures loadMaterialTextures(aiMaterial * mat, aiTextureType type,
const std::string & typeName); const std::string & typeName);
void sortModels(); void sortModels();
// Model Private Members // Model Private Members
ModelMesh::Textures mTexturesLoaded; ModelMesh::Textures mTexturesLoaded;
std::vector<ModelMesh> mMeshes; std::vector<ModelMesh> mMeshes;
std::string mDirectory; std::string mDirectory;
const char * mVertexShader, * mFragmentShader, * mName; const char * mVertexShader, * mFragmentShader, * mName;
}; };
}
#endif // QTK_MODEL_H #endif // QTK_MODEL_H

View File

@ -7,3 +7,5 @@
##############################################################################*/ ##############################################################################*/
#include <object.h> #include <object.h>
using namespace Qtk;

View File

@ -14,48 +14,50 @@
#include <QOpenGLVertexArrayObject> #include <QOpenGLVertexArrayObject>
#include <mesh.h> #include <mesh.h>
#include <qtkapi.h>
namespace Qtk {
class QTKAPI Object : public QObject {
Q_OBJECT
class Object : public QObject { public:
Q_OBJECT friend MeshRenderer;
// Initialize an object with no shape data assigned
Object(const char * name)
: mName(name), mVBO(QOpenGLBuffer::VertexBuffer)
{ }
// Initialize an object with shape data assigned
Object(const char * name, const ShapeBase & shape)
: mName(name), mVBO(QOpenGLBuffer::VertexBuffer), mShape(shape)
{ }
public: ~Object() {}
friend MeshRenderer;
// Initialize an object with no shape data assigned
Object(const char * name)
: mName(name), mVBO(QOpenGLBuffer::VertexBuffer)
{ }
// Initialize an object with shape data assigned
Object(const char * name, const ShapeBase & shape)
: mName(name), mVBO(QOpenGLBuffer::VertexBuffer), mShape(shape)
{ }
~Object() {} inline const Vertices & vertices() { return mShape.mVertices;}
inline const Indices & indices() { return mShape.mIndices;}
inline const Colors & colors() { return mShape.mColors;}
inline const TexCoords & texCoords() { return mShape.mTexCoords;}
inline const Normals & normals() { return mShape.mNormals;}
inline QOpenGLTexture & texture() const { return *mTexture;}
inline const Vertices & vertices() { return mShape.mVertices;} virtual inline void setVertices(const Vertices & value) { mShape.mVertices = value;}
inline const Indices & indices() { return mShape.mIndices;} virtual inline void setIndices(const Indices & value) { mShape.mIndices = value;}
inline const Colors & colors() { return mShape.mColors;} virtual inline void setColors(const Colors & value) { mShape.mColors = value;}
inline const TexCoords & texCoords() { return mShape.mTexCoords;} virtual inline void setTexCoords(const TexCoords & value) { mShape.mTexCoords = value;}
inline const Normals & normals() { return mShape.mNormals;} virtual inline void setNormals(const Normals & value) { mShape.mNormals = value;}
inline QOpenGLTexture & texture() const { return *mTexture;} virtual inline void setShape(const Shape & value) { mShape = value;}
virtual inline void setVertices(const Vertices & value) { mShape.mVertices = value;} QOpenGLBuffer mVBO, mNBO;
virtual inline void setIndices(const Indices & value) { mShape.mIndices = value;} QOpenGLVertexArrayObject mVAO;
virtual inline void setColors(const Colors & value) { mShape.mColors = value;} QOpenGLShaderProgram mProgram;
virtual inline void setTexCoords(const TexCoords & value) { mShape.mTexCoords = value;}
virtual inline void setNormals(const Normals & value) { mShape.mNormals = value;}
virtual inline void setShape(const Shape & value) { mShape = value;}
QOpenGLBuffer mVBO, mNBO; Transform3D mTransform;
QOpenGLVertexArrayObject mVAO; Shape mShape;
QOpenGLShaderProgram mProgram;
Transform3D mTransform; const char * mName;
Shape mShape; private:
QOpenGLTexture * mTexture;
const char * mName; };
private: }
QOpenGLTexture * mTexture;
};
#endif // QTK_OBJECT_H #endif // QTK_OBJECT_H

View File

@ -1,24 +1,23 @@
/*############################################################################## /*##############################################################################
## Author: Shaun Reed ## ## Author: Shaun Reed ##
## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ## ## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ##
## About: Manage files and resources used by qtk ## ## About: Main window for Qt6 OpenGL widget application ##
## ## ## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## ## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################*/ ##############################################################################*/
#ifndef QTK_QTKAPI_H
#define QTK_QTKAPI_H
#include "resourcemanager.h" #include <QtCore/QtGlobal>
#include <algorithm>
#include <string>
#include <QtGlobal>
static std::string nixPath(std::string path) #ifdef QTK_SHARED
{ # if defined(QTK_EXPORT)
#ifdef Q_OS_WINDOWS # define QTKAPI Q_DECL_EXPORT
std::replace(path.begin(), path.end(), '\\', '/'); # else
# define QTKAPI Q_DECL_IMPORT
# endif
#else
# define QTKAPI
#endif #endif
return path;
}
std::string RM::resourcesDir = #endif //QTK_QTKAPI_H
std::string(__FILE__).substr(0, nixPath(__FILE__).find("src/"))
+ "resources/";

2
src/qtkresources.h.in Normal file
View File

@ -0,0 +1,2 @@
#define QTK_RESOURCES "@QTK_RESOURCES@"

View File

@ -9,36 +9,36 @@
#include <QKeyEvent> #include <QKeyEvent>
#include <input.h> #include <input.h>
#include <qtkwidget.h>
#include <mesh.h> #include <mesh.h>
#include <object.h> #include <abstractscene.h>
#include <scene.h>
#include <mainwidget.h>
using namespace Qtk;
/******************************************************************************* /*******************************************************************************
* Constructors, Destructors * Constructors, Destructors
******************************************************************************/ ******************************************************************************/
MainWidget::MainWidget() : mDebugLogger(Q_NULLPTR) QtkWidget::QtkWidget() : mScene(Q_NULLPTR), mDebugLogger(Q_NULLPTR)
{ {
initializeWidget(); initializeWidget();
} }
// Constructor for using this widget in QtDesigner // Constructor for using this widget in QtDesigner
MainWidget::MainWidget(QWidget *parent) : QOpenGLWidget(parent), mDebugLogger(Q_NULLPTR) QtkWidget::QtkWidget(QWidget *parent) : QOpenGLWidget(parent),
mScene(Q_NULLPTR), mDebugLogger(Q_NULLPTR)
{ {
initializeWidget(); initializeWidget();
} }
MainWidget::MainWidget(const QSurfaceFormat &format) QtkWidget::QtkWidget(const QSurfaceFormat &format)
: mDebugLogger(Q_NULLPTR) : mScene(Q_NULLPTR), mDebugLogger(Q_NULLPTR)
{ {
setFormat(format); setFormat(format);
setFocusPolicy(Qt::ClickFocus); setFocusPolicy(Qt::ClickFocus);
} }
MainWidget::~MainWidget() QtkWidget::~QtkWidget()
{ {
makeCurrent(); makeCurrent();
teardownGL(); teardownGL();
@ -49,80 +49,26 @@ MainWidget::~MainWidget()
* Private Member Functions * Private Member Functions
******************************************************************************/ ******************************************************************************/
void MainWidget::teardownGL() void QtkWidget::teardownGL()
{ {
// Nothing to teardown yet... // Nothing to teardown yet...
} }
void MainWidget::initObjects()
{
mScene = new Scene;
// Drawing a primitive object using Qt and OpenGL
// The Object class only stores basic QOpenGL* members and shape data
// + Within mainwidget, mObject serves as a basic QOpenGL example
mObject = new Object("testObject");
mObject->setVertices(Cube(QTK_DRAW_ELEMENTS).vertices());
mObject->setIndices(Cube(QTK_DRAW_ELEMENTS).indices());
mObject->mProgram.create();
mObject->mProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,
":/solid-ambient.vert");
mObject->mProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,
":/solid-ambient.frag");
mObject->mProgram.link();
mObject->mProgram.bind();
mObject->mVAO.create();
mObject->mVAO.bind();
mObject->mVBO.create();
mObject->mVBO.setUsagePattern(QOpenGLBuffer::StaticDraw);
mObject->mVBO.bind();
mObject->mVBO.allocate(mObject->vertices().data(),
mObject->vertices().size()
* sizeof(mObject->vertices()[0]));
mObject->mProgram.enableAttributeArray(0);
mObject->mProgram.setAttributeBuffer(0, GL_FLOAT, 0,
3, sizeof(mObject->vertices()[0]));
mObject->mProgram.setUniformValue("uColor", QVector3D(1.0f, 0.0f, 0.0f));
mObject->mProgram.setUniformValue("uLightColor", WHITE);
mObject->mProgram.setUniformValue("uAmbientStrength", 0.75f);
mObject->mVBO.release();
mObject->mVAO.release();
mObject->mProgram.release();
mObject->mTransform.setTranslation(13.0f, 0.0f, -2.0f);
}
/******************************************************************************* /*******************************************************************************
* Inherited Virtual Member Functions * Inherited Virtual Member Functions
******************************************************************************/ ******************************************************************************/
void MainWidget::paintGL() void QtkWidget::paintGL()
{ {
// Clear buffers // Clear buffers
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
// Draw the scene first, since it handles drawing our skybox // Draw the scene first, since it handles drawing our skybox
mScene->draw(); if (mScene != Q_NULLPTR) mScene->draw();
// Draw any additional objects within mainwidget manually
mObject->mProgram.bind();
mObject->mVAO.bind();
mObject->mProgram.setUniformValue("uModel", mObject->mTransform.toMatrix());
mObject->mProgram.setUniformValue("uView", Scene::Camera().toMatrix());
mObject->mProgram.setUniformValue("uProjection", Scene::Projection());
glDrawElements(GL_TRIANGLES, mObject->indices().size(),
GL_UNSIGNED_INT, mObject->indices().data());
mObject->mVAO.release();
mObject->mProgram.release();
} }
void MainWidget::initializeGL() void QtkWidget::initializeGL()
{ {
initializeOpenGLFunctions(); initializeOpenGLFunctions();
// Connect the frameSwapped signal to call the update() function // Connect the frameSwapped signal to call the update() function
@ -150,12 +96,9 @@ void MainWidget::initializeGL()
glClearDepth(1.0f); glClearDepth(1.0f);
glClearColor(0.0f, 0.25f, 0.0f, 0.0f); glClearColor(0.0f, 0.25f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Initialize default objects within the scene
initObjects();
} }
void MainWidget::resizeGL(int width, int height) void QtkWidget::resizeGL(int width, int height)
{ {
Scene::Projection().setToIdentity(); Scene::Projection().setToIdentity();
Scene::Projection().perspective(45.0f, Scene::Projection().perspective(45.0f,
@ -168,16 +111,16 @@ void MainWidget::resizeGL(int width, int height)
* Protected Slots * Protected Slots
******************************************************************************/ ******************************************************************************/
void MainWidget::update() void QtkWidget::update()
{ {
updateCameraInput(); updateCameraInput();
mScene->update(); if (mScene != Q_NULLPTR) mScene->update();
QWidget::update(); QWidget::update();
} }
void MainWidget::messageLogged(const QOpenGLDebugMessage &msg) void QtkWidget::messageLogged(const QOpenGLDebugMessage &msg)
{ {
QString error; QString error;
@ -242,7 +185,7 @@ void MainWidget::messageLogged(const QOpenGLDebugMessage &msg)
* Protected Helpers * Protected Helpers
******************************************************************************/ ******************************************************************************/
void MainWidget::keyPressEvent(QKeyEvent *event) void QtkWidget::keyPressEvent(QKeyEvent *event)
{ {
if (event->isAutoRepeat()) { if (event->isAutoRepeat()) {
// Do not repeat input while a key is held down // Do not repeat input while a key is held down
@ -252,7 +195,7 @@ void MainWidget::keyPressEvent(QKeyEvent *event)
} }
} }
void MainWidget::keyReleaseEvent(QKeyEvent *event) void QtkWidget::keyReleaseEvent(QKeyEvent *event)
{ {
if (event->isAutoRepeat()) { if (event->isAutoRepeat()) {
event->ignore(); event->ignore();
@ -261,12 +204,12 @@ void MainWidget::keyReleaseEvent(QKeyEvent *event)
} }
} }
void MainWidget::mousePressEvent(QMouseEvent *event) void QtkWidget::mousePressEvent(QMouseEvent *event)
{ {
Input::registerMousePress(event->button()); Input::registerMousePress(event->button());
} }
void MainWidget::mouseReleaseEvent(QMouseEvent *event) void QtkWidget::mouseReleaseEvent(QMouseEvent *event)
{ {
Input::registerMouseRelease(event->button()); Input::registerMouseRelease(event->button());
} }
@ -276,7 +219,7 @@ void MainWidget::mouseReleaseEvent(QMouseEvent *event)
* Private Helpers * Private Helpers
******************************************************************************/ ******************************************************************************/
void MainWidget::initializeWidget() void QtkWidget::initializeWidget()
{ {
QSurfaceFormat format; QSurfaceFormat format;
format.setRenderableType(QSurfaceFormat::OpenGL); format.setRenderableType(QSurfaceFormat::OpenGL);
@ -294,7 +237,7 @@ void MainWidget::initializeWidget()
setFocusPolicy(Qt::ClickFocus); setFocusPolicy(Qt::ClickFocus);
} }
void MainWidget::printContextInformation() void QtkWidget::printContextInformation()
{ {
QString glType; QString glType;
QString glVersion; QString glVersion;
@ -330,7 +273,7 @@ void MainWidget::printContextInformation()
} }
void MainWidget::updateCameraInput() void QtkWidget::updateCameraInput()
{ {
Input::update(); Input::update();
// Camera Transformation // Camera Transformation

74
src/qtkwidget.h Normal file
View File

@ -0,0 +1,74 @@
/*##############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ##
## About: Main window for Qt6 OpenGL widget application ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################*/
#ifndef QTK_QTKWIDGET_H
#define QTK_QTKWIDGET_H
#include <iostream>
#include <QMatrix4x4>
#include <QOpenGLDebugLogger>
#include <QOpenGLFunctions>
#include <QOpenGLWidget>
#include <qtkapi.h>
#include <abstractscene.h>
namespace Qtk {
class QTKAPI QtkWidget : public QOpenGLWidget,
protected QOpenGLFunctions {
Q_OBJECT;
public:
// Constructors
QtkWidget();
explicit QtkWidget(QWidget *parent);
explicit QtkWidget(const QSurfaceFormat &format);
~QtkWidget() override;
private:
void teardownGL();
public:
// Inherited virtual Members
void paintGL() override;
void initializeGL() override;
void resizeGL(int width, int height) override;
inline Qtk::Scene * getScene() {return mScene;}
inline void setScene(Qtk::Scene * scene) {
if (mScene != Q_NULLPTR) delete mScene;
mScene = scene;
}
protected slots:
void update();
#ifdef QTK_DEBUG
void messageLogged(const QOpenGLDebugMessage &msg);
#endif
// Protected Helpers
protected:
void keyPressEvent(QKeyEvent *event);
void keyReleaseEvent(QKeyEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
private:
// Private helpers
void initializeWidget();
void updateCameraInput();
Qtk::Scene * mScene;
#ifdef QTK_DEBUG
void printContextInformation();
QOpenGLDebugLogger * mDebugLogger;
#endif
};
}
#endif // QTK_QTKWIDGET_H

View File

@ -6,23 +6,25 @@
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## ## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################*/ ##############################################################################*/
#include <scene.h> #include <abstractscene.h>
#include <skybox.h>
#include <texture.h> #include <texture.h>
#include <skybox.h> using namespace Qtk;
Skybox::Skybox(std::string right, std::string top, std::string front, Skybox::Skybox(std::string right, std::string top, std::string front,
std::string left, std::string bottom, std::string back, std::string left, std::string bottom, std::string back,
const std::string & name) const std::string & name)
: mCubeMap(Texture::initCubeMap( : mVBO(QOpenGLBuffer::VertexBuffer),
QImage(right.c_str()).mirrored(), QImage(top.c_str()),
QImage(front.c_str()), QImage(left.c_str()),
QImage(bottom.c_str()), QImage(back.c_str()))),
mVBO(QOpenGLBuffer::VertexBuffer),
mVertices(Cube(QTK_DRAW_ELEMENTS).vertices()), mVertices(Cube(QTK_DRAW_ELEMENTS).vertices()),
mIndices(Cube(QTK_DRAW_ELEMENTS).indices()) mIndices(Cube(QTK_DRAW_ELEMENTS).indices())
{ init();} {
init();
mCubeMap = Texture::initCubeMap(
QImage(right.c_str()).mirrored(), QImage(top.c_str()),
QImage(front.c_str()), QImage(left.c_str()),
QImage(bottom.c_str()), QImage(back.c_str()));
}
Skybox::Skybox(std::string name) Skybox::Skybox(std::string name)
: Skybox(":/right.png", ":/top.png", ":/front.png", : Skybox(":/right.png", ":/top.png", ":/front.png",
@ -87,13 +89,11 @@ void Skybox::init()
mVBO.setUsagePattern(QOpenGLBuffer::StaticDraw); mVBO.setUsagePattern(QOpenGLBuffer::StaticDraw);
mVBO.bind(); mVBO.bind();
// Allocate vertex positions into VBO // Allocate vertex positions into VBO
mVBO.allocate(mVertices.data(), mVBO.allocate(mVertices.data(), mVertices.size() * sizeof(mVertices[0]));
mVertices.size() * sizeof(mVertices[0]));
// Enable attribute array for vertex positions // Enable attribute array for vertex positions
mProgram.enableAttributeArray(0); mProgram.enableAttributeArray(0);
mProgram.setAttributeBuffer(0, GL_FLOAT, 0, mProgram.setAttributeBuffer(0, GL_FLOAT, 0, 3, sizeof(QVector3D));
3, sizeof(QVector3D));
// Set shader texture unit to 0 // Set shader texture unit to 0
mProgram.setUniformValue("uTexture", 0); mProgram.setUniformValue("uTexture", 0);

View File

@ -10,39 +10,42 @@
#include <QImage> #include <QImage>
#include <QOpenGLBuffer> #include <QOpenGLBuffer>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram> #include <QOpenGLShaderProgram>
#include <QOpenGLTexture> #include <QOpenGLTexture>
#include <QOpenGLVertexArrayObject> #include <QOpenGLVertexArrayObject>
#include <QOpenGLFunctions>
#include <camera3d.h> #include <camera3d.h>
#include <mesh.h> #include <mesh.h>
#include <qtkapi.h>
class Skybox : protected QOpenGLFunctions { namespace Qtk {
public: class QTKAPI Skybox : protected QOpenGLFunctions {
// Delegate this constructor to use default skybox images public:
// + This allows creating a skybox with no arguments ( auto s = new Skybox; ) // Delegate this constructor to use default skybox images
explicit Skybox(std::string name="Skybox"); // + This allows creating a skybox with no arguments ( auto s = new Skybox; )
explicit Skybox(QOpenGLTexture * cubeMap, const std::string & name="Skybox"); explicit Skybox(std::string name="Skybox");
// Constructor, Destructor explicit Skybox(QOpenGLTexture * cubeMap, const std::string & name="Skybox");
Skybox(std::string right, std::string top, std::string front, // Constructor, Destructor
std::string left, std::string bottom, std::string back, Skybox(std::string right, std::string top, std::string front,
const std::string & name="Skybox"); std::string left, std::string bottom, std::string back,
~Skybox() {} const std::string & name="Skybox");
~Skybox() {}
void draw(); void draw();
private: private:
void init(); void init();
Vertices mVertices; Vertices mVertices;
Indices mIndices; Indices mIndices;
QOpenGLShaderProgram mProgram; QOpenGLShaderProgram mProgram;
QOpenGLVertexArrayObject mVAO; QOpenGLVertexArrayObject mVAO;
QOpenGLBuffer mVBO; QOpenGLBuffer mVBO;
QOpenGLTexture * mCubeMap; QOpenGLTexture * mCubeMap;
}; };
}
#endif // QTK_SKYBOX_H #endif // QTK_SKYBOX_H

View File

@ -11,6 +11,7 @@
#include <texture.h> #include <texture.h>
using namespace Qtk;
QImage * Texture::initImage(const char * image, bool flipX, bool flipY) QImage * Texture::initImage(const char * image, bool flipX, bool flipY)
{ {

View File

@ -11,32 +11,35 @@
#include <QOpenGLTexture> #include <QOpenGLTexture>
#include <qtkapi.h>
class Texture { namespace Qtk {
public: class QTKAPI Texture {
~Texture() {} public:
~Texture() {}
// QImage // QImage
static QImage * initImage(const char * image, static QImage * initImage(const char * image,
bool flipX=false, bool flipY=false); bool flipX=false, bool flipY=false);
// 2D Texture // 2D Texture
static QOpenGLTexture * initTexture2D(const char * texture, static QOpenGLTexture * initTexture2D(const char * texture,
bool flipX=false, bool flipY=false); bool flipX=false, bool flipY=false);
// Cube maps // Cube maps
static QOpenGLTexture * initCubeMap(QImage right, QImage top, static QOpenGLTexture * initCubeMap(QImage right, QImage top,
QImage front, QImage left, QImage front, QImage left,
QImage bottom, QImage back); QImage bottom, QImage back);
// Overloads for cube map initialization // Overloads for cube map initialization
static QOpenGLTexture * initCubeMap(const char * tile); static QOpenGLTexture * initCubeMap(const char * tile);
static QOpenGLTexture * initCubeMap(const char * right, const char * top, static QOpenGLTexture * initCubeMap(const char * right, const char * top,
const char * front, const char * left, const char * front, const char * left,
const char * bottom, const char * back); const char * bottom, const char * back);
private: private:
// Private ctor to prevent creating instances of this class // Private ctor to prevent creating instances of this class
Texture() {} Texture() {}
}; };
}
#endif // QTOPENGL_TEXTURE_H #endif // QTOPENGL_TEXTURE_H

View File

@ -9,6 +9,7 @@
#include <transform3D.h> #include <transform3D.h>
using namespace Qtk;
const QVector3D Transform3D::LocalForward(0.0f, 0.0f, 1.0f); const QVector3D Transform3D::LocalForward(0.0f, 0.0f, 1.0f);
const QVector3D Transform3D::LocalUp(0.0f, 1.0f, 0.0f); const QVector3D Transform3D::LocalUp(0.0f, 1.0f, 0.0f);
@ -110,35 +111,41 @@ QVector3D Transform3D::right() const
* QT Streams * QT Streams
******************************************************************************/ ******************************************************************************/
QDebug operator<<(QDebug dbg, const Transform3D & transform) namespace Qtk {
{ #ifndef QT_NO_DEBUG_STREAM
dbg << "Transform3D\n{\n"; QDebug operator<<(QDebug dbg, const Transform3D & transform)
dbg << "Position: <" << transform.translation().x() << ", " {
<< transform.translation().y() << ", " dbg << "Transform3D\n{\n";
<< transform.translation().z() << ">\n"; dbg << "Position: <" << transform.translation().x() << ", "
dbg << "Scale: <" << transform.scale().x() << ", " << transform.translation().y() << ", "
<< transform.scale().y() << ", " << transform.translation().z() << ">\n";
<< transform.scale().z() << ">\n"; dbg << "Scale: <" << transform.scale().x() << ", "
dbg << "Rotation: <" << transform.rotation().x() << ", " << transform.scale().y() << ", "
<< transform.rotation().y() << ", " << transform.scale().z() << ">\n";
<< transform.rotation().z() << " | " << dbg << "Rotation: <" << transform.rotation().x() << ", "
transform.rotation().scalar() << ">\n}"; << transform.rotation().y() << ", "
return dbg; << transform.rotation().z() << " | " <<
transform.rotation().scalar() << ">\n}";
return dbg;
} }
#endif
QDataStream & operator<<(QDataStream & out, const Transform3D & transform) #ifndef QT_NO_DATASTREAM
{ QDataStream & operator<<(QDataStream & out, const Transform3D & transform)
out << transform.mTranslation; {
out << transform.mScale; out << transform.mTranslation;
out << transform.mRotation; out << transform.mScale;
return out; out << transform.mRotation;
} return out;
}
QDataStream & operator>>(QDataStream & in, Transform3D & transform) QDataStream & operator>>(QDataStream & in, Transform3D & transform)
{ {
in >> transform.mTranslation; in >> transform.mTranslation;
in >> transform.mScale; in >> transform.mScale;
in >> transform.mRotation; in >> transform.mRotation;
transform.m_dirty = true; transform.m_dirty = true;
return in; return in;
}
#endif
} }

View File

@ -10,108 +10,116 @@
#ifndef QTK_TRANSFORM3D_H #ifndef QTK_TRANSFORM3D_H
#define QTK_TRANSFORM3D_H #define QTK_TRANSFORM3D_H
#include <QDebug>
#include <QMatrix4x4> #include <QMatrix4x4>
#include <QQuaternion> #include <QQuaternion>
#include <QVector3D> #include <QVector3D>
#ifndef QT_NO_DEBUG_STREAM
#include <QDebug>
#endif
class Transform3D #include <qtkapi.h>
{
public:
// Constructors
inline Transform3D() : m_dirty(true),
mScale(1.0f, 1.0f, 1.0f),
mTranslation(0.0f, 0.0f, 0.0f) { }
// namespace Qtk {
// Transformations class QTKAPI Transform3D
{
public:
// Constructors
inline Transform3D() : m_dirty(true),
mScale(1.0f, 1.0f, 1.0f),
mTranslation(0.0f, 0.0f, 0.0f) { }
void translate(const QVector3D & dt); //
inline void translate(float dx, float dy, float dz) // Transformations
{ translate(QVector3D(dx, dy, dz));}
// Scale object with multiplication void translate(const QVector3D & dt);
void scale(const QVector3D & ds); inline void translate(float dx, float dy, float dz)
inline void scale(float dx, float dy, float dz) { translate(QVector3D(dx, dy, dz));}
{ scale(QVector3D(dx, dy, dz));}
inline void scale(float factor)
{ scale(QVector3D(factor, factor, factor));}
// Multiplying by a rotation // Scale object with multiplication
void rotate(const QQuaternion & dr); void scale(const QVector3D & ds);
inline void rotate(float angle, const QVector3D & axis) inline void scale(float dx, float dy, float dz)
{ rotate(QQuaternion::fromAxisAndAngle(axis, angle));} { scale(QVector3D(dx, dy, dz));}
inline void rotate(float angle, float ax, float ay, float az) inline void scale(float factor)
{ rotate(QQuaternion::fromAxisAndAngle(ax, ay, az, angle));} { scale(QVector3D(factor, factor, factor));}
// Scale object by addition // Multiplying by a rotation
void grow(const QVector3D & ds); void rotate(const QQuaternion & dr);
inline void grow(float dx, float dy, float dz) inline void rotate(float angle, const QVector3D & axis)
{ grow(QVector3D(dx, dy, dz));} { rotate(QQuaternion::fromAxisAndAngle(axis, angle));}
inline void grow(float factor) inline void rotate(float angle, float ax, float ay, float az)
{ grow(QVector3D(factor, factor, factor));} { rotate(QQuaternion::fromAxisAndAngle(ax, ay, az, angle));}
// // Scale object by addition
// Setters void grow(const QVector3D & ds);
inline void grow(float dx, float dy, float dz)
{ grow(QVector3D(dx, dy, dz));}
inline void grow(float factor)
{ grow(QVector3D(factor, factor, factor));}
// Set object position //
void setTranslation(const QVector3D & t); // Setters
inline void setTranslation(float x, float y, float z)
{ setTranslation(QVector3D(x, y, z));}
// Set object scale // Set object position
void setScale(const QVector3D & s); void setTranslation(const QVector3D & t);
inline void setScale(float x, float y, float z) inline void setTranslation(float x, float y, float z)
{ setScale(QVector3D(x, y, z));} { setTranslation(QVector3D(x, y, z));}
inline void setScale(float k)
{ setScale(QVector3D(k, k, k));}
// Set object rotation // Set object scale
void setRotation(const QQuaternion & r); void setScale(const QVector3D & s);
inline void setRotation(float angle, const QVector3D & axis) inline void setScale(float x, float y, float z)
{ setRotation(QQuaternion::fromAxisAndAngle(axis, angle));} { setScale(QVector3D(x, y, z));}
inline void setRotation(float angle, float ax, float ay, float az) inline void setScale(float k)
{ setRotation(QQuaternion::fromAxisAndAngle(ax, ay, az, angle));} { setScale(QVector3D(k, k, k));}
// // Set object rotation
// Accessors void setRotation(const QQuaternion & r);
inline void setRotation(float angle, const QVector3D & axis)
{ setRotation(QQuaternion::fromAxisAndAngle(axis, angle));}
inline void setRotation(float angle, float ax, float ay, float az)
{ setRotation(QQuaternion::fromAxisAndAngle(ax, ay, az, angle));}
inline const QVector3D & translation() const { return mTranslation;} //
inline const QVector3D & scale() const { return mScale; } // Accessors
inline const QQuaternion & rotation() const { return mRotation; }
const QMatrix4x4 & toMatrix();
QVector3D forward() const; inline const QVector3D & translation() const { return mTranslation;}
QVector3D up() const; inline const QVector3D & scale() const { return mScale; }
QVector3D right() const; inline const QQuaternion & rotation() const { return mRotation; }
const QMatrix4x4 & toMatrix();
static const QVector3D LocalForward, LocalUp, LocalRight; QVector3D forward() const;
QVector3D up() const;
QVector3D right() const;
private: static const QVector3D LocalForward, LocalUp, LocalRight;
QVector3D mTranslation;
QQuaternion mRotation; private:
QVector3D mScale; QVector3D mTranslation;
QMatrix4x4 mWorld; QQuaternion mRotation;
QVector3D mScale;
QMatrix4x4 mWorld;
bool m_dirty;
bool m_dirty;
#ifndef QT_NO_DATASTREAM #ifndef QT_NO_DATASTREAM
friend QDataStream &operator<<(QDataStream & out, const Transform3D & transform); friend QDataStream &operator<<(QDataStream & out, const Transform3D & transform);
friend QDataStream &operator>>(QDataStream & in, Transform3D & transform); friend QDataStream &operator>>(QDataStream & in, Transform3D & transform);
#endif #endif
}; };
Q_DECLARE_TYPEINFO(Transform3D, Q_MOVABLE_TYPE);
// Qt Streams // Qt Streams
#ifndef QT_NO_DEBUG_STREAM #ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const Transform3D & transform); QDebug operator<<(QDebug dbg, const Transform3D & transform);
#endif #endif
#ifndef QT_NO_DATASTREAM #ifndef QT_NO_DATASTREAM
QDataStream &operator<<(QDataStream & out, const Transform3D & transform); QDataStream &operator<<(QDataStream & out, const Transform3D & transform);
QDataStream &operator>>(QDataStream & in, Transform3D & transform); QDataStream &operator>>(QDataStream & in, Transform3D & transform);
#endif #endif
}
Q_DECLARE_TYPEINFO(Qtk::Transform3D, Q_MOVABLE_TYPE);
#endif // QTK_TRANSFORM3D_H #endif // QTK_TRANSFORM3D_H