From 249a2b44467e3b1fe7f7164544ea8e2f0b87d1ab Mon Sep 17 00:00:00 2001 From: Shaun Reed Date: Sun, 7 Aug 2022 13:12:12 -0400 Subject: [PATCH] Work on separating widget from main application + Thanks @OgreTransporter for help in #4! + Closes #4 --- CMakeLists.txt | 187 ++++++++++++++++++++++++------- {src => app}/mainwindow.cpp | 6 +- {src => app}/mainwindow.h | 7 +- {src => app}/mainwindow.ui | 2 +- {src => app}/resourcemanager.cpp | 17 +-- {src => app}/resourcemanager.h | 6 +- {src => app}/scene.cpp | 127 +++++++++++---------- {src => app}/scene.h | 37 +++--- src/abstractscene.cpp | 48 ++++++++ src/abstractscene.h | 54 +++++++++ src/camera3d.cpp | 1 + src/camera3d.h | 66 +++++------ src/input.cpp | 1 + src/input.h | 89 +++++++-------- src/mainwidget.cpp | 75 ++----------- src/mainwidget.h | 88 ++++++++------- src/mesh.cpp | 1 + src/mesh.h | 122 ++++++++++---------- src/meshrenderer.cpp | 8 +- src/meshrenderer.h | 103 ++++++++--------- src/model.cpp | 8 +- src/model.h | 165 +++++++++++++-------------- src/object.cpp | 2 + src/object.h | 72 ++++++------ src/qtkapi.h | 23 ++++ src/skybox.cpp | 6 +- src/skybox.h | 47 ++++---- src/texture.cpp | 1 + src/texture.h | 47 ++++---- src/transform3D.cpp | 63 ++++++----- src/transform3D.h | 152 +++++++++++++------------ 31 files changed, 913 insertions(+), 718 deletions(-) rename {src => app}/mainwindow.cpp (63%) rename {src => app}/mainwindow.h (66%) rename {src => app}/mainwindow.ui (97%) rename {src => app}/resourcemanager.cpp (61%) rename {src => app}/resourcemanager.h (93%) rename {src => app}/scene.cpp (88%) rename {src => app}/scene.h (51%) create mode 100644 src/abstractscene.cpp create mode 100644 src/abstractscene.h create mode 100644 src/qtkapi.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1dd8633..d6516cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ ## ## ## Project for working with OpenGL and Qt6 widgets ## ################################################################################ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.2) project( #[[NAME]] Qtk @@ -16,72 +16,177 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) +option(QTK_DEBUG "Enable debugger" ON) +option(BUILD_SHARED_LIBS "Build shared library" ON) +option(ASSIMP_NEW_INTERFACE "Use assimp::assimp as target instead of assimp" OFF) + +################################################################################ +# External Libraries +################################################################################ + # For CLion builds, point CMAKE_PREFIX_PATH to Qt6 install directory list(APPEND CMAKE_PREFIX_PATH $ENV{HOME}/Code/Clones/Qt/6.3.1/gcc_64/) + +# Find Qt 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() -################################################################################ -# External Libraries -################################################################################ - +# Find Assimp # https://github.com/assimp/assimp/commit/6ac8279977c3a54118551e549d77329497116f66 find_package(assimp REQUIRED) -option(ASSIMP_NEW_INTERFACE "Use assimp::assimp as target instead of assimp" OFF) + include(GenerateExportHeader) +################################################################################ +# Qtk +################################################################################ + +set(PUBLIC_HEADERS + src/mainwidget.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/mainwidget.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 +) +qt_add_library(qtk-widget STATIC ${PUBLIC_HEADERS} ${SOURCE_FILES}) +target_include_directories(qtk-widget PRIVATE src/ app/) +generate_export_header(qtk-widget) + +set_target_properties(qtk-widget PROPERTIES + PUBLIC_HEADER "${PUBLIC_HEADERS}" + VERSION ${PROJECT_VERSION} +) + +target_include_directories(qtk-widget PUBLIC $) +if(BUILD_SHARED_LIBS) + target_compile_definitions(qtk-widget PRIVATE QTK_EXPORT PUBLIC QTK_SHARED) + target_link_libraries(qtk-widget PRIVATE Qt6::OpenGLWidgets) + if(ASSIMP_NEW_INTERFACE) + target_link_libraries(qtk-widget PUBLIC assimp::assimp) + else() + target_link_libraries(qtk-widget PUBLIC assimp) + endif() +else() + target_compile_definitions(qtk-widget PUBLIC QTK_STATIC) + target_link_libraries(qtk-widget PUBLIC Qt6::OpenGLWidgets) + if(ASSIMP_NEW_INTERFACE) + target_link_libraries(qtk-widget PUBLIC assimp::assimp) + else() + target_link_libraries(qtk-widget PUBLIC assimp) + endif() +endif() + +if(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 + # /bin on DLL systems and /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 ################################################################################ +file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/resources.h "#ifndef QTK_RESOURCES_H\n#define QTK_RESOURCES_H\n#define QTK_RESOURCES_DIR \"${CMAKE_SOURCE_DIR}/resources\"\n#endif\n") + # Add our Qt resources.qrc file to our application -set(SOURCES app/main.cpp) -qt6_add_big_resources(SOURCES resources.qrc) -qt_add_executable(qtk ${SOURCES}) - -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 +set(QTK_APP_SOURCES app/main.cpp + app/mainwindow.cpp app/mainwindow.h app/mainwindow.ui + app/scene.cpp app/scene.h + app/resourcemanager.cpp app/resourcemanager.h + ${CMAKE_CURRENT_BINARY_DIR}/resources.h ) -qt_add_library(main-widget STATIC ${SOURCES}) +qt6_add_big_resources(QTK_APP_SOURCES resources.qrc) -target_include_directories(main-widget PUBLIC src/) -if(ASSIMP_NEW_INTERFACE) - target_link_libraries(main-widget PRIVATE assimp::assimp) -else() - target_link_libraries(main-widget PRIVATE assimp) -endif() -target_link_libraries(main-widget PUBLIC Qt6::OpenGLWidgets) -if(WIN32) - find_package(OpenGL REQUIRED) - target_link_libraries(main-widget PUBLIC OpenGL::GL) -endif() +qt_add_executable(qtk-app ${QTK_APP_SOURCES}) +target_include_directories(qtk-app PRIVATE src/ app/) -target_link_libraries(qtk PUBLIC main-widget) +# Link qtk-app executable to main qtk-widget library +target_link_libraries(qtk-app PRIVATE Qt6::OpenGLWidgets qtk-widget) -# Link qtk executable to main main-widget library -set_target_properties(qtk PROPERTIES +set_target_properties(qtk-app PROPERTIES WIN32_EXECUTABLE TRUE MACOSX_BUNDLE TRUE MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} ) +install(TARGETS qtk-app + BUNDLE DESTINATION . + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} +) -generate_export_header(main-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-app + POST_BUILD + COMMAND set PATH=%PATH%$${qt6_install_prefix} + COMMAND Qt6::windeployqt --dir "${CMAKE_BINARY_DIR}/windeployqt" "$/$" + ) + install(DIRECTORY "${CMAKE_BINARY_DIR}/windeployqt/" DESTINATION bin) + endif() + if(MSVC AND TARGET Qt6::qmake) + set(VSUSER_FILE ${CMAKE_CURRENT_BINARY_DIR}/qtk-app.vcxproj.user) + file(TO_NATIVE_PATH "${assimp_DIR}/bin" assimp_bin) + file(WRITE ${VSUSER_FILE} "\n") + file(APPEND ${VSUSER_FILE} "\n") + file(APPEND ${VSUSER_FILE} " \n") + file(APPEND ${VSUSER_FILE} " Path=$(SolutionDir)\\lib\\$(Configuration);${qt6_install_prefix};${assimp_bin};$(Path)\n") + file(APPEND ${VSUSER_FILE} "$(LocalDebuggerEnvironment)\n") + file(APPEND ${VSUSER_FILE} " WindowsLocalDebugger\n") + file(APPEND ${VSUSER_FILE} " \n") + file(APPEND ${VSUSER_FILE} "\n") + endif() +endif() diff --git a/src/mainwindow.cpp b/app/mainwindow.cpp similarity index 63% rename from src/mainwindow.cpp rename to app/mainwindow.cpp index 6ee1f0b..713d43e 100644 --- a/src/mainwindow.cpp +++ b/app/mainwindow.cpp @@ -1,11 +1,13 @@ -#include "mainwindow.h" -#include "ui_mainwindow.h" +#include +#include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); + mScene = new ExampleScene(); + ui->openGLWidget->setScene(mScene); setWindowIcon(QIcon("../resources/icon.png")); } diff --git a/src/mainwindow.h b/app/mainwindow.h similarity index 66% rename from src/mainwindow.h rename to app/mainwindow.h index 9efee87..04397bb 100644 --- a/src/mainwindow.h +++ b/app/mainwindow.h @@ -3,13 +3,15 @@ #include -#include "main-widget_export.h" +#include +#include + namespace Ui { class MainWindow; } -class MAIN_WIDGET_EXPORT MainWindow : public QMainWindow +class QTK_WIDGET_EXPORT MainWindow : public QMainWindow { Q_OBJECT @@ -19,6 +21,7 @@ public: private: Ui::MainWindow *ui; + Qtk::Scene * mScene; }; #endif // MAINWINDOW_H diff --git a/src/mainwindow.ui b/app/mainwindow.ui similarity index 97% rename from src/mainwindow.ui rename to app/mainwindow.ui index 83f5142..13f9903 100644 --- a/src/mainwindow.ui +++ b/app/mainwindow.ui @@ -14,7 +14,7 @@ Qtk - MainWindow - + 10 diff --git a/src/resourcemanager.cpp b/app/resourcemanager.cpp similarity index 61% rename from src/resourcemanager.cpp rename to app/resourcemanager.cpp index b1b6b60..f17ce50 100644 --- a/src/resourcemanager.cpp +++ b/app/resourcemanager.cpp @@ -6,19 +6,4 @@ ## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## ##############################################################################*/ -#include "resourcemanager.h" -#include -#include -#include - -static std::string nixPath(std::string path) -{ -#ifdef Q_OS_WINDOWS - std::replace(path.begin(), path.end(), '\\', '/'); -#endif - return path; -} - -std::string RM::resourcesDir = - std::string(__FILE__).substr(0, nixPath(__FILE__).find("src/")) - + "resources/"; +#include diff --git a/src/resourcemanager.h b/app/resourcemanager.h similarity index 93% rename from src/resourcemanager.h rename to app/resourcemanager.h index 7189677..b702720 100644 --- a/src/resourcemanager.h +++ b/app/resourcemanager.h @@ -8,6 +8,8 @@ #include +#include + #ifndef QTK_RESOURCEMANAGER_H #define QTK_RESOURCEMANAGER_H @@ -26,10 +28,8 @@ public: */ static std::string getPath(const std::string & path) { // 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_DIR + path.substr(1) : path; } - - static std::string resourcesDir; } RM; #endif //QTK_RESOURCEMANAGER_H diff --git a/src/scene.cpp b/app/scene.cpp similarity index 88% rename from src/scene.cpp rename to app/scene.cpp index 17929f4..9b0b91d 100644 --- a/src/scene.cpp +++ b/app/scene.cpp @@ -6,32 +6,27 @@ ## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## ##############################################################################*/ +#include #include -#include #include #include #include - #include +#include - -Camera3D Scene::mCamera; -QMatrix4x4 Scene::mProjection; - +using namespace Qtk; /******************************************************************************* * Constructors, Destructors ******************************************************************************/ -Scene::Scene() +ExampleScene::ExampleScene() { - mCamera.transform().setTranslation(0.0f, 0.0f, 20.0f); - mCamera.transform().setRotation(-5.0f, 0.0f, 1.0f, 0.0f); - - init(); + Camera().transform().setTranslation(0.0f, 0.0f, 20.0f); + Camera().transform().setRotation(-5.0f, 0.0f, 1.0f, 0.0f); } -Scene::~Scene() +ExampleScene::~ExampleScene() { delete mTestPhong; delete mTestSpecular; @@ -39,6 +34,7 @@ Scene::~Scene() delete mTestAmbient; for (auto & mesh : mMeshes) delete mesh; for (auto & model : mModels) delete model; + delete mSkybox; } @@ -46,10 +42,13 @@ Scene::~Scene() * Public Member Functions ******************************************************************************/ -void Scene::init() +void ExampleScene::init() { + Qtk::Skybox * sb = new Qtk::Skybox("Skybox"); + setSkybox(sb); + // 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->setShaders(":/solid-phong.vert", ":/solid-phong.frag"); mTestPhong->init(); @@ -76,7 +75,7 @@ void Scene::init() // 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->setShaders(":/solid-ambient.vert", ":/solid-ambient.frag"); mTestAmbient->init(); @@ -100,7 +99,7 @@ void Scene::init() mTestAmbient->mProgram.release(); // 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->setShaders(":/solid-diffuse.vert", ":/solid-diffuse.frag"); mTestDiffuse->init(); @@ -124,7 +123,7 @@ void Scene::init() mTestDiffuse->mProgram.release(); // 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->setShaders(":/solid-specular.vert", ":/solid-specular.frag"); mTestSpecular->init(); @@ -152,31 +151,31 @@ void Scene::init() // // 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 mModels.back()->flipTexture("diffuse.jpg", false, true); 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); // Sometimes the models are very large mModels.back()->mTransform.scale(0.0025f); 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.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.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.rotate(-90.0f, 1.0f, 0.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); @@ -186,7 +185,7 @@ void Scene::init() // Render an alien with specular // Test alien Model with phong lighting and specular mapping 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.scale(0.25f); // This function changes values we have allocated in a buffer, so init() after @@ -194,7 +193,7 @@ void Scene::init() mMeshes.back()->init(); 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") ); 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 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.scale(0.25f); @@ -223,7 +222,7 @@ void Scene::init() mMeshes.back()->init(); mModels.push_back( - new Model("spartanTest", ":/models/spartan/spartan.obj", + new Qtk::Model("spartanTest", ":/models/spartan/spartan.obj", ":/model-normals.vert", ":/model-normals.frag") ); 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 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.scale(0.25f); mMeshes.back()->setDrawType(GL_LINE_LOOP); @@ -251,7 +250,7 @@ void Scene::init() mMeshes.back()->init(); 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()->setShaders(":/phong.vert", ":/phong.frag"); 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 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.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.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()->setDrawType(GL_LINE_LOOP); 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.scale(0.25f); 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.scale(0.25f); 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 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()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag"); mMeshes.back()->init(); @@ -344,7 +343,7 @@ void Scene::init() // RGB Normals cube to show normals are correct with QTK_DRAW_ELEMENTS_NORMALS 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()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag"); mMeshes.back()->init(); @@ -369,7 +368,7 @@ void Scene::init() // + UVs required duplicating element position data from QTK_DRAW_ELEMENTS // + This is because the same position must use different UV coordinates 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()->setShaders(":/texture2d.vert", ":/texture2d.frag"); mMeshes.back()->init(); @@ -397,7 +396,7 @@ void Scene::init() // Test drawing a cube with texture coordinates using glDrawElements 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()->setShaders(":/texture2d.vert", ":/texture2d.frag"); mMeshes.back()->init(); @@ -423,7 +422,7 @@ void Scene::init() // Texturing a cube using a cube map // + Cube map texturing works with both QTK_DRAW_ARRAYS and QTK_DRAW_ELEMENTS 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.setRotation(45.0f, 0.0f, 1.0f, 0.0f); mMeshes.back()->setShaders(":/texture-cubemap.vert", ":/texture-cubemap.frag"); @@ -450,7 +449,7 @@ void Scene::init() // Create a cube with custom shaders // + Apply RGB normals shader and spin the cube for a neat effect 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()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag"); mMeshes.back()->init(); @@ -472,7 +471,7 @@ void Scene::init() // RGB Normals triangle to show normals are correct with QTK_DRAW_ARRAYS 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()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag"); mMeshes.back()->init(); @@ -493,7 +492,7 @@ void Scene::init() // RGB Normals triangle to show normals are correct with QTK_DRAW_ELEMENTS mMeshes.push_back( - new MeshRenderer("rgbTriangleElementsTest", + new Qtk::MeshRenderer("rgbTriangleElementsTest", Triangle(QTK_DRAW_ELEMENTS_NORMALS))); mMeshes.back()->mTransform.setTranslation(7.0f, 0.0f, 4.0f); mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag"); @@ -515,7 +514,7 @@ void Scene::init() // Test drawing triangle with glDrawArrays with texture coordinates 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()->setShaders(":/texture2d.vert", ":/texture2d.frag"); mMeshes.back()->init(); @@ -543,7 +542,7 @@ void Scene::init() // Test drawing triangle with glDrawElements with texture coordinates mMeshes.push_back( - new MeshRenderer("testTriangleElementsUV", + new Qtk::MeshRenderer("testTriangleElementsUV", Triangle(QTK_DRAW_ELEMENTS_NORMALS))); mMeshes.back()->mTransform.setTranslation(-2.5f, 0.0f, -1.0f); mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag"); @@ -575,7 +574,7 @@ void Scene::init() // Example of a cube with no lighting applied 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()->setShaders(":/solid-perspective.vert", ":/solid-perspective.frag"); @@ -586,24 +585,24 @@ void Scene::init() // Create objects that represent light sources for lighting examples 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.scale(0.25f); 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.scale(0.25f); 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.scale(0.25f); } -void Scene::draw() +void ExampleScene::draw() { - mSkybox.draw(); + mSkybox->draw(); for (auto & model : mModels) model->draw(); @@ -616,13 +615,13 @@ void Scene::draw() "uLightPosition", MeshRenderer::getInstance("phongLight")->mTransform.translation()); mTestPhong->setUniform("uCameraPosition", - Scene::Camera().transform().translation()); + ExampleScene::Camera().transform().translation()); mTestPhong->mProgram.release(); mTestPhong->draw(); mTestAmbient->mProgram.bind(); mTestAmbient->setUniform("uCameraPosition", - Scene::Camera().transform().translation()); + ExampleScene::Camera().transform().translation()); mTestAmbient->mProgram.release(); mTestAmbient->draw(); @@ -632,7 +631,7 @@ void Scene::draw() mTestDiffuse->setUniform( "uLightPosition", MeshRenderer::getInstance("diffuseLight")->mTransform.translation()); - mTestDiffuse->setUniform("uCameraPosition", Scene::Camera().transform().translation()); + mTestDiffuse->setUniform("uCameraPosition", ExampleScene::Camera().transform().translation()); mTestDiffuse->mProgram.release(); mTestDiffuse->draw(); @@ -643,43 +642,43 @@ void Scene::draw() mTestSpecular->setUniform( "uLightPosition", MeshRenderer::getInstance("specularLight")->mTransform.translation()); - mTestSpecular->setUniform("uCameraPosition", Scene::Camera().transform().translation()); + mTestSpecular->setUniform("uCameraPosition", ExampleScene::Camera().transform().translation()); mTestSpecular->mProgram.release(); mTestSpecular->draw(); } -void Scene::update() +void ExampleScene::update() { auto position = MeshRenderer::getInstance("alienTestLight")->mTransform.translation(); Model::getInstance("alienTest")->setUniform( "uLight.position", position); Model::getInstance("alienTest")->setUniform( - "uCameraPosition", Scene::Camera().transform().translation()); + "uCameraPosition", ExampleScene::Camera().transform().translation()); auto posMatrix = Model::getInstance("alienTest")->mTransform.toMatrix(); Model::getInstance("alienTest")->setUniform( "uMVP.normalMatrix", posMatrix.normalMatrix()); Model::getInstance("alienTest")->setUniform( "uMVP.model", posMatrix); Model::getInstance("alienTest")->setUniform( - "uMVP.view", Scene::Camera().toMatrix()); + "uMVP.view", ExampleScene::Camera().toMatrix()); 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); position = MeshRenderer::getInstance("spartanTestLight")->mTransform.translation(); Model::getInstance("spartanTest")->setUniform( "uLight.position", position); Model::getInstance("spartanTest")->setUniform( - "uCameraPosition", Scene::Camera().transform().translation()); + "uCameraPosition", ExampleScene::Camera().transform().translation()); posMatrix = Model::getInstance("spartanTest")->mTransform.toMatrix(); Model::getInstance("spartanTest")->setUniform( "uMVP.normalMatrix", posMatrix.normalMatrix()); Model::getInstance("spartanTest")->setUniform( "uMVP.model", posMatrix); Model::getInstance("spartanTest")->setUniform( - "uMVP.view", Scene::Camera().toMatrix()); + "uMVP.view", ExampleScene::Camera().toMatrix()); 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); @@ -691,16 +690,16 @@ void Scene::update() MeshRenderer::getInstance("testPhong")->setUniform( "uLight.position", position); MeshRenderer::getInstance("testPhong")->setUniform( - "uCameraPosition", Scene::Camera().transform().translation()); + "uCameraPosition", ExampleScene::Camera().transform().translation()); posMatrix = MeshRenderer::getInstance("testPhong")->mTransform.toMatrix(); MeshRenderer::getInstance("testPhong")->setUniform( "uMVP.normalMatrix", posMatrix.normalMatrix()); MeshRenderer::getInstance("testPhong")->setUniform( "uMVP.model", posMatrix); MeshRenderer::getInstance("testPhong")->setUniform( - "uMVP.view", Scene::Camera().toMatrix()); + "uMVP.view", ExampleScene::Camera().toMatrix()); MeshRenderer::getInstance("testPhong")->setUniform( - "uMVP.projection", Scene::Projection()); + "uMVP.projection", ExampleScene::Projection()); MeshRenderer::getInstance("testPhong")->mProgram.release(); // Rotate lighting example cubes diff --git a/src/scene.h b/app/scene.h similarity index 51% rename from src/scene.h rename to app/scene.h index 8d5964d..016c6c2 100644 --- a/src/scene.h +++ b/app/scene.h @@ -6,40 +6,31 @@ ## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## ##############################################################################*/ -#ifndef QTK_SCENE_H -#define QTK_SCENE_H +#ifndef QTK_EXAMPLE_SCENE_H +#define QTK_EXAMPLE_SCENE_H +#include #include #include #include -class MeshRenderer; -class Model; -class Scene { +class ExampleScene : public Qtk::Scene { public: - Scene(); - ~Scene(); + ExampleScene(); + ~ExampleScene(); - void init(); - void draw(); - void update(); + virtual void init(); + virtual void draw(); + virtual void update(); - static Camera3D & Camera() { return mCamera;} - static QMatrix4x4 View() { return mCamera.toMatrix();} - static QMatrix4x4 & Projection() { return mProjection;} private: - static Camera3D mCamera; - static QMatrix4x4 mProjection; - Skybox mSkybox; - MeshRenderer * mTestPhong; - MeshRenderer * mTestSpecular; - MeshRenderer * mTestDiffuse; - MeshRenderer * mTestAmbient; - std::vector mMeshes; - std::vector mModels; + Qtk::MeshRenderer * mTestPhong; + Qtk::MeshRenderer * mTestSpecular; + Qtk::MeshRenderer * mTestDiffuse; + Qtk::MeshRenderer * mTestAmbient; }; -#endif // QTK_SCENE_H +#endif // QTK_EXAMPLE_SCENE_H diff --git a/src/abstractscene.cpp b/src/abstractscene.cpp new file mode 100644 index 0000000..4d1dcdd --- /dev/null +++ b/src/abstractscene.cpp @@ -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 +#include +#include +#include + +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(); +} + diff --git a/src/abstractscene.h b/src/abstractscene.h new file mode 100644 index 0000000..1072b60 --- /dev/null +++ b/src/abstractscene.h @@ -0,0 +1,54 @@ +/*############################################################################## +## 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 +#include +#include +#include + +#include + + +namespace Qtk { + class Scene : protected QOpenGLFunctions { + friend class MainWidget; + public: + Scene(); + ~Scene(); + + virtual void init() = 0; + virtual void draw() = 0; + 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 mMeshes; + std::vector mModels; + }; +} + +#endif // QTK_SCENE_H diff --git a/src/camera3d.cpp b/src/camera3d.cpp index fde5e22..968c837 100644 --- a/src/camera3d.cpp +++ b/src/camera3d.cpp @@ -8,6 +8,7 @@ #include +using namespace Qtk; const QVector3D Camera3D::LocalForward(0.0f, 0.0f, -1.0f); const QVector3D Camera3D::LocalUp(0.0f, 1.0f, 0.0f); diff --git a/src/camera3d.h b/src/camera3d.h index 632b883..a26d769 100644 --- a/src/camera3d.h +++ b/src/camera3d.h @@ -12,51 +12,53 @@ #include #include +#include +namespace Qtk { + class QTKAPI Camera3D { + public: + // Constants + static const QVector3D LocalForward; + static const QVector3D LocalUp; + static const QVector3D LocalRight; -class Camera3D { -public: - // Constants - static const QVector3D LocalForward; - static const QVector3D LocalUp; - static const QVector3D LocalRight; + // Accessors + inline Transform3D & transform() { return mTransform;} + inline const QVector3D & translation() const + { return mTransform.translation();} + inline const QQuaternion & rotation() const + { return mTransform.rotation();} + const QMatrix4x4 & toMatrix(); - // Accessors - inline Transform3D & transform() { return mTransform;} - inline const QVector3D & translation() const - { return mTransform.translation();} - inline const QQuaternion & rotation() const - { return mTransform.rotation();} - const QMatrix4x4 & toMatrix(); + // Queries + inline QVector3D forward() const + { return mTransform.rotation().rotatedVector(LocalForward);} + inline QVector3D right() const + { return mTransform.rotation().rotatedVector(LocalRight);} + inline QVector3D up() const + { return mTransform.rotation().rotatedVector(LocalUp);} - // Queries - inline QVector3D forward() const - { return mTransform.rotation().rotatedVector(LocalForward);} - inline QVector3D right() const - { return mTransform.rotation().rotatedVector(LocalRight);} - inline QVector3D up() const - { return mTransform.rotation().rotatedVector(LocalUp);} - -private: - Transform3D mTransform; - QMatrix4x4 mWorld; + private: + Transform3D mTransform; + QMatrix4x4 mWorld; #ifndef QT_NO_DATASTREAM - friend QDataStream & operator<<(QDataStream & out, Camera3D & transform); - friend QDataStream & operator>>(QDataStream & in, Camera3D & transform); + friend QDataStream & operator<<(QDataStream & out, Camera3D & transform); + friend QDataStream & operator>>(QDataStream & in, Camera3D & transform); #endif -}; - -Q_DECLARE_TYPEINFO(Camera3D, Q_MOVABLE_TYPE); + }; // Qt Streams #ifndef QT_NO_DATASTREAM -QDataStream & operator<<(QDataStream & out, const Camera3D & transform); -QDataStream & operator>>(QDataStream & in, Camera3D & transform); + QDataStream & operator<<(QDataStream & out, const Camera3D & transform); + QDataStream & operator>>(QDataStream & in, Camera3D & transform); #endif #ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug dbg, const Camera3D & transform); + QDebug operator<<(QDebug dbg, const Camera3D & transform); #endif +} + +Q_DECLARE_TYPEINFO(Qtk::Camera3D, Q_MOVABLE_TYPE); #endif // QTK_CAMERA3D_H diff --git a/src/input.cpp b/src/input.cpp index 9aa5b67..cca776d 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -13,6 +13,7 @@ #include +using namespace Qtk; /******************************************************************************* * Static Helper Structs diff --git a/src/input.h b/src/input.h index cf6f44c..96d006f 100644 --- a/src/input.h +++ b/src/input.h @@ -12,52 +12,53 @@ #include #include +#include -class Input { - friend class MainWidget; -public: +namespace Qtk { + class QTKAPI Input { + friend class MainWidget; + public: + // Possible key states + enum InputState + { + InputInvalid, + InputRegistered, + InputUnregistered, + InputTriggered, + InputPressed, + InputReleased + }; - // Possible key states - enum InputState - { - InputInvalid, - InputRegistered, - InputUnregistered, - InputTriggered, - InputPressed, - InputReleased + // 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(); }; - - // 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 diff --git a/src/mainwidget.cpp b/src/mainwidget.cpp index e1a82cf..1170cbb 100644 --- a/src/mainwidget.cpp +++ b/src/mainwidget.cpp @@ -9,30 +9,30 @@ #include #include -#include -#include -#include - #include +#include +#include +using namespace Qtk; /******************************************************************************* * Constructors, Destructors ******************************************************************************/ -MainWidget::MainWidget() : mDebugLogger(Q_NULLPTR) +MainWidget::MainWidget() : mScene(Q_NULLPTR), mDebugLogger(Q_NULLPTR) { initializeWidget(); } // Constructor for using this widget in QtDesigner -MainWidget::MainWidget(QWidget *parent) : QOpenGLWidget(parent), mDebugLogger(Q_NULLPTR) +MainWidget::MainWidget(QWidget *parent) : QOpenGLWidget(parent), + mScene(Q_NULLPTR), mDebugLogger(Q_NULLPTR) { initializeWidget(); } MainWidget::MainWidget(const QSurfaceFormat &format) - : mDebugLogger(Q_NULLPTR) + : mScene(Q_NULLPTR), mDebugLogger(Q_NULLPTR) { setFormat(format); setFocusPolicy(Qt::ClickFocus); @@ -54,49 +54,6 @@ void MainWidget::teardownGL() // 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 @@ -108,18 +65,7 @@ void MainWidget::paintGL() glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // Draw the scene first, since it handles drawing our skybox - 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(); + if (mScene != Q_NULLPTR) mScene->privDraw(); } void MainWidget::initializeGL() @@ -150,9 +96,6 @@ void MainWidget::initializeGL() glClearDepth(1.0f); glClearColor(0.0f, 0.25f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - -// Initialize default objects within the scene - initObjects(); } void MainWidget::resizeGL(int width, int height) @@ -172,7 +115,7 @@ void MainWidget::update() { updateCameraInput(); - mScene->update(); + if (mScene != Q_NULLPTR) mScene->update(); QWidget::update(); } diff --git a/src/mainwidget.h b/src/mainwidget.h index ff00232..219c125 100644 --- a/src/mainwidget.h +++ b/src/mainwidget.h @@ -15,57 +15,61 @@ #include #include -#define QTK_DEBUG +#include +#include -class MeshRenderer; -class Model; -class Object; -class Scene; -class Skybox; -class Texture; -class MainWidget : public QOpenGLWidget, - protected QOpenGLFunctions { -Q_OBJECT; +namespace Qtk { + class QTKAPI MainWidget : public QOpenGLWidget, + protected QOpenGLFunctions { + Q_OBJECT; -public: - // Constructors - MainWidget(); - explicit MainWidget(QWidget *parent); - explicit MainWidget(const QSurfaceFormat &format); - ~MainWidget() override; + public: + // Constructors + MainWidget(); + explicit MainWidget(QWidget *parent); + explicit MainWidget(const QSurfaceFormat &format); + ~MainWidget() override; -private: - void teardownGL(); - void initObjects(); + private: + void teardownGL(); -public: - // Inherited virtual Members - void paintGL() override; - void initializeGL() override; - void resizeGL(int width, int height) override; + 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); + inline Scene * getScene() {return mScene;} + inline void setScene(Scene * scene) { + if (mScene != Q_NULLPTR) delete mScene; + mScene = scene; + } - // Protected Helpers -protected: - void keyPressEvent(QKeyEvent *event); - void keyReleaseEvent(QKeyEvent *event); - void mousePressEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *event); + protected slots: + void update(); +#ifdef QTK_DEBUG + void messageLogged(const QOpenGLDebugMessage &msg); +#endif -private: - // Private helpers - void initializeWidget(); - void printContextInformation(); - void updateCameraInput(); + // Protected Helpers + protected: + void keyPressEvent(QKeyEvent *event); + void keyReleaseEvent(QKeyEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); - Scene * mScene; - Object * mObject; + private: + // Private helpers + void initializeWidget(); + void updateCameraInput(); - QOpenGLDebugLogger * mDebugLogger; -}; + Scene * mScene; +#ifdef QTK_DEBUG + void printContextInformation(); + QOpenGLDebugLogger * mDebugLogger; +#endif + }; +} #endif // QTK_MAINWIDGET_H diff --git a/src/mesh.cpp b/src/mesh.cpp index 5dab145..3f765f6 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -8,6 +8,7 @@ #include +using namespace Qtk; Cube::Cube(DrawMode mode) { diff --git a/src/mesh.h b/src/mesh.h index 49db0c2..41cd579 100644 --- a/src/mesh.h +++ b/src/mesh.h @@ -12,25 +12,27 @@ #include #include +#include #include -class MeshRenderer; -class Object; +namespace Qtk { + class MeshRenderer; + class Object; -// Define vertices for drawing a cube using two faces (8 vertex points) -// Front Vertices + // Define vertices for drawing a cube using two faces (8 vertex points) + // Front Vertices #define VERTEX_FTR QVector3D( 0.5f, 0.5f, 0.5f) // 1 #define VERTEX_FTL QVector3D(-0.5f, 0.5f, 0.5f) // 2 #define VERTEX_FBL QVector3D(-0.5f, -0.5f, 0.5f) // 3 #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_BTL QVector3D(-0.5f, 0.5f, -0.5f) // 6 #define VERTEX_BBL QVector3D(-0.5f, -0.5f, -0.5f) // 7 #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_DOWN QVector3D(0.0f, -1.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_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_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, \ - VECTOR_UP, VECTOR_UP, VECTOR_UP + VECTOR_UP, VECTOR_UP, VECTOR_UP #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, \ - VECTOR_LEFT, VECTOR_LEFT, VECTOR_LEFT + VECTOR_LEFT, VECTOR_LEFT, VECTOR_LEFT #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, \ - VECTOR_FORWARD, VECTOR_FORWARD, VECTOR_FORWARD + VECTOR_FORWARD, VECTOR_FORWARD, VECTOR_FORWARD #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 BLACK VECTOR_ZERO #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_CORNER QVector2D(1.0f, 1.0f) + typedef std::vector Vertices; + typedef std::vector Colors; + typedef std::vector Indices; + typedef std::vector TexCoords; + typedef std::vector Normals; -typedef std::vector Vertices; -typedef std::vector Colors; -typedef std::vector Indices; -typedef std::vector TexCoords; -typedef std::vector Normals; + enum DrawMode { QTK_DRAW_ARRAYS, QTK_DRAW_ELEMENTS, QTK_DRAW_ELEMENTS_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 { - 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) - {} + inline const Vertices & vertices() const { return mVertices;} + inline const Indices & indices() const { return mIndices;} + inline const Colors & colors() const { return mColors;} + inline const TexCoords & texCoords() const { return mTexCoords;} + inline const Normals & normals() const { return mNormals;} - inline const Vertices & vertices() const { return mVertices;} - inline const Indices & indices() const { return mIndices;} - inline const Colors & colors() const { return mColors;} - inline const TexCoords & texCoords() const { return mTexCoords;} - inline const Normals & normals() const { return mNormals;} + protected: + DrawMode mDrawMode; -protected: - DrawMode mDrawMode; + Vertices mVertices; + Colors mColors; + Indices mIndices; + TexCoords mTexCoords; + Normals mNormals; + }; - Vertices mVertices; - Colors mColors; - Indices mIndices; - TexCoords mTexCoords; - Normals mNormals; -}; + struct Shape : public ShapeBase { + friend MeshRenderer; + friend Object; + Shape () {} + Shape(const ShapeBase & rhs) : ShapeBase(rhs) {} -struct Shape : public ShapeBase { - friend MeshRenderer; - friend Object; - Shape () {} - Shape(const ShapeBase & rhs) : ShapeBase(rhs) {} - - 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;} -}; + 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 -class Mesh { + class QTKAPI Mesh { -}; + }; -struct Cube : public ShapeBase { - Cube(DrawMode mode=QTK_DRAW_ARRAYS); -}; + struct QTKAPI Cube : public ShapeBase { + Cube(DrawMode mode=QTK_DRAW_ARRAYS); + }; -struct Triangle : public ShapeBase { - Triangle(DrawMode mode=QTK_DRAW_ARRAYS); -}; + struct QTKAPI Triangle : public ShapeBase { + Triangle(DrawMode mode=QTK_DRAW_ARRAYS); + }; +} #endif // QTK_MESH_H diff --git a/src/meshrenderer.cpp b/src/meshrenderer.cpp index f18849a..0d7a114 100644 --- a/src/meshrenderer.cpp +++ b/src/meshrenderer.cpp @@ -8,14 +8,14 @@ #include -#include +#include +#include #include -#include - +using namespace Qtk; // 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) : Object(name, shape), mVertexShader(":/multi-color.vert"), diff --git a/src/meshrenderer.h b/src/meshrenderer.h index 609492b..edde65b 100644 --- a/src/meshrenderer.h +++ b/src/meshrenderer.h @@ -10,68 +10,71 @@ #include #include +#include -class MeshRenderer : public Object { -public: - // Delegate constructors - MeshRenderer(const char * name, Vertices vertices, Indices indices, - DrawMode mode=QTK_DRAW_ARRAYS) - : MeshRenderer(name, ShapeBase(mode, vertices, indices)) - {} - MeshRenderer(const char * name) - : MeshRenderer(name, Cube(QTK_DRAW_ELEMENTS)) - {} - // Constructor - MeshRenderer(const char * name, const ShapeBase &shape); - ~MeshRenderer(); +namespace Qtk { + class QTKAPI MeshRenderer : public Object { + public: + // Delegate constructors + MeshRenderer(const char * name, Vertices vertices, Indices indices, + DrawMode mode=QTK_DRAW_ARRAYS) + : MeshRenderer(name, ShapeBase(mode, vertices, indices)) + {} + MeshRenderer(const char * name) + : MeshRenderer(name, Cube(QTK_DRAW_ELEMENTS)) + {} + // Constructor + MeshRenderer(const char * name, const ShapeBase &shape); + ~MeshRenderer(); - // Retrieve a mesh by name stored within a static QHash - static MeshRenderer * getInstance(const QString & name); + // Retrieve a mesh by name stored within a static QHash + static MeshRenderer * getInstance(const QString & name); - void init(); - void draw(); + void init(); + void draw(); - // Draw types like GL_TRIANGLES, GL_POINTS, GL_LINES, etc - void setDrawType(int drawType) { mDrawType = drawType;} + // Draw types like GL_TRIANGLES, GL_POINTS, GL_LINES, etc + void setDrawType(int drawType) { mDrawType = drawType;} - // Shader settings - inline void setShaderVertex(const std::string & vert) { mVertexShader = vert;} - inline void setShaderFragment(const std::string & frag) - { mFragmentShader = frag;} - void setShaders(const std::string & vert, const std::string & frag); + // Shader settings + inline void setShaderVertex(const std::string & vert) { mVertexShader = vert;} + inline void setShaderFragment(const std::string & frag) + { mFragmentShader = frag;} + void setShaders(const std::string & vert, const std::string & frag); - template - inline void setUniform(int location, T value) - { mProgram.setUniformValue(location, value);} + template + inline void setUniform(int location, T value) + { mProgram.setUniformValue(location, value);} - template - inline void setUniform(const char * location, T value) - { mProgram.setUniformValue(location, value);} + template + inline void setUniform(const char * location, T value) + { mProgram.setUniformValue(location, value);} - // Set MVP matrix using this Object's transform - // + View and projection provided by MainWidget static members - void setUniformMVP(const char * model="uModel", const char * view="uView", - const char * projection="uProjection"); + // Set MVP matrix using this Object's transform + // + View and projection provided by MainWidget static members + void setUniformMVP(const char * model="uModel", const char * view="uView", + const char * projection="uProjection"); - // Sets the texture to the image at the given path - // + Sets mHasTexture to enable texture binding in draw() - void setTexture(const char * path); - void setTexture(QOpenGLTexture * texture); + // Sets the texture to the image at the given path + // + Sets mHasTexture to enable texture binding in draw() + void setTexture(const char * path); + void setTexture(QOpenGLTexture * texture); - // These functions modify data stored in a VBO - // + After calling them, the VBO will need to be reallocated - void setShape(const Shape & value) override; - void setColor(const QVector3D & color); + // These functions modify data stored in a VBO + // + After calling them, the VBO will need to be reallocated + void setShape(const Shape & value) override; + void setColor(const QVector3D & color); - // Static QHash of all mesh objects within the scene - typedef QHash MeshManager; -private: - static MeshManager sInstances; + // Static QHash of all mesh objects within the scene + typedef QHash MeshManager; + private: + static MeshManager sInstances; - int mDrawType; - bool mHasTexture; - std::string mVertexShader, mFragmentShader; -}; + int mDrawType; + bool mHasTexture; + std::string mVertexShader, mFragmentShader; + }; +} #endif // QTK_MESHRENDERER_H diff --git a/src/model.cpp b/src/model.cpp index f814328..1f1128a 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -9,12 +9,12 @@ #include -#include -#include -#include - +#include #include +#include +#include +using namespace Qtk; Model::ModelManager Model::mManager; diff --git a/src/model.h b/src/model.h index e3a7c67..20b5e96 100644 --- a/src/model.h +++ b/src/model.h @@ -16,7 +16,6 @@ #include #include #include -#include // Assimp #include @@ -24,117 +23,119 @@ #include // QTK +#include #include +namespace Qtk { + struct QTKAPI ModelVertex { + QVector3D mPosition; + QVector3D mNormal; + QVector3D mTangent; + QVector3D mBitangent; + QVector2D mTextureCoord; + }; -struct ModelVertex { - QVector3D mPosition; - QVector3D mNormal; - QVector3D mTangent; - QVector3D mBitangent; - QVector2D mTextureCoord; -}; + struct QTKAPI ModelTexture { + GLuint mID; + QOpenGLTexture * mTexture; + std::string mType; + std::string mPath; + }; -struct ModelTexture { - GLuint mID; - QOpenGLTexture * mTexture; - std::string mType; - std::string mPath; -}; + class Model; -class Model; + class QTKAPI ModelMesh : protected QOpenGLFunctions { + public: + friend Model; + typedef std::vector Vertices; + typedef std::vector Indices; + typedef std::vector Textures; -class ModelMesh : protected QOpenGLFunctions { -public: - friend Model; - typedef std::vector Vertices; - typedef std::vector Indices; - typedef std::vector 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), + // 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), mVBO(new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer)), mEBO(new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer)), mVertices(std::move(vertices)), mIndices(std::move(indices)), mTextures(std::move(textures)) - { initMesh(vertexShader, fragmentShader);} - ~ModelMesh() {} + { initMesh(vertexShader, fragmentShader);} + ~ModelMesh() {} -private: - void initMesh(const char * vert, const char * frag); + private: + void initMesh(const char * vert, const char * frag); - // ModelMesh Private Members - QOpenGLBuffer * mVBO, * mEBO; - QOpenGLVertexArrayObject * mVAO; - QOpenGLShaderProgram * mProgram; + // ModelMesh Private Members + QOpenGLBuffer * mVBO, * mEBO; + QOpenGLVertexArrayObject * mVAO; + QOpenGLShaderProgram * mProgram; -public: - inline void draw() { draw(*mProgram);} - void draw(QOpenGLShaderProgram & shader); + public: + inline void draw() { draw(*mProgram);} + void draw(QOpenGLShaderProgram & shader); - // ModelMesh Public Members - Vertices mVertices; - Indices mIndices; - Textures mTextures; - Transform3D mTransform; -}; + // ModelMesh Public Members + Vertices mVertices; + Indices mIndices; + Textures mTextures; + Transform3D mTransform; + }; -class Model : public QObject { -Q_OBJECT + class QTKAPI Model : public QObject { + Q_OBJECT -public: - inline Model(const char * name, const char * path, - const char * vertexShader=":/model-basic.vert", - const char * fragmentShader=":/model-basic.frag") - : mName(name), mVertexShader(vertexShader), + public: + inline Model(const char * name, const char * path, + const char * vertexShader=":/model-basic.vert", + const char * fragmentShader=":/model-basic.frag") + : mName(name), mVertexShader(vertexShader), mFragmentShader(fragmentShader) - { loadModel(path);} - inline ~Model() { mManager.remove(mName);} + { loadModel(path);} + inline ~Model() { mManager.remove(mName);} - void draw(); - void draw(QOpenGLShaderProgram & shader); + void draw(); + void draw(QOpenGLShaderProgram & shader); - void flipTexture(const std::string & fileName, - bool flipX=false, bool flipY=true); + void flipTexture(const std::string & fileName, + bool flipX=false, bool flipY=true); - template - void setUniform(const char * location, T value) - { - for (auto & mesh : mMeshes) { - mesh.mProgram->bind(); + template + void setUniform(const char * location, T value) + { + for (auto & mesh : mMeshes) { + 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 ModelManager; -private: - static ModelManager mManager; - void loadModel(const std::string & path); - void processNode(aiNode * node, const aiScene * scene); - ModelMesh processMesh(aiMesh * mesh, const aiScene * scene); - ModelMesh::Textures loadMaterialTextures(aiMaterial * mat, aiTextureType type, - const std::string & typeName); - void sortModels(); + typedef QHash ModelManager; + private: + static ModelManager mManager; + void loadModel(const std::string & path); + void processNode(aiNode * node, const aiScene * scene); + ModelMesh processMesh(aiMesh * mesh, const aiScene * scene); + ModelMesh::Textures loadMaterialTextures(aiMaterial * mat, aiTextureType type, + const std::string & typeName); + void sortModels(); - // Model Private Members + // Model Private Members - ModelMesh::Textures mTexturesLoaded; - std::vector mMeshes; - std::string mDirectory; - const char * mVertexShader, * mFragmentShader, * mName; -}; + ModelMesh::Textures mTexturesLoaded; + std::vector mMeshes; + std::string mDirectory; + const char * mVertexShader, * mFragmentShader, * mName; + }; +} #endif // QTK_MODEL_H diff --git a/src/object.cpp b/src/object.cpp index 463b0aa..eb2d546 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -7,3 +7,5 @@ ##############################################################################*/ #include + +using namespace Qtk; diff --git a/src/object.h b/src/object.h index c48b62e..03169fb 100644 --- a/src/object.h +++ b/src/object.h @@ -14,48 +14,50 @@ #include #include +#include +namespace Qtk { + class QTKAPI Object : public QObject { + Q_OBJECT -class Object : public QObject { -Q_OBJECT + public: + 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: - 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() {} - ~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;} - 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;} + virtual inline void setVertices(const Vertices & value) { mShape.mVertices = value;} + virtual inline void setIndices(const Indices & value) { mShape.mIndices = value;} + virtual inline void setColors(const Colors & value) { mShape.mColors = value;} + 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;} - virtual inline void setVertices(const Vertices & value) { mShape.mVertices = value;} - virtual inline void setIndices(const Indices & value) { mShape.mIndices = value;} - virtual inline void setColors(const Colors & value) { mShape.mColors = value;} - 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; + QOpenGLVertexArrayObject mVAO; + QOpenGLShaderProgram mProgram; - QOpenGLBuffer mVBO, mNBO; - QOpenGLVertexArrayObject mVAO; - QOpenGLShaderProgram mProgram; + Transform3D mTransform; + Shape mShape; - Transform3D mTransform; - Shape mShape; - - const char * mName; -private: - QOpenGLTexture * mTexture; -}; + const char * mName; + private: + QOpenGLTexture * mTexture; + }; +} #endif // QTK_OBJECT_H diff --git a/src/qtkapi.h b/src/qtkapi.h new file mode 100644 index 0000000..a34cdae --- /dev/null +++ b/src/qtkapi.h @@ -0,0 +1,23 @@ +/*############################################################################## +## 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_QTKAPI_H +#define QTK_QTKAPI_H + +#include + +#ifdef QTK_SHARED +# if defined(QTK_EXPORT) +# define QTKAPI Q_DECL_EXPORT +# else +# define QTKAPI Q_DECL_IMPORT +# endif +#else +# define QTKAPI +#endif + +#endif //QTK_QTKAPI_H diff --git a/src/skybox.cpp b/src/skybox.cpp index 6b7db76..09afa03 100644 --- a/src/skybox.cpp +++ b/src/skybox.cpp @@ -6,11 +6,11 @@ ## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## ##############################################################################*/ -#include +#include +#include #include -#include - +using namespace Qtk; Skybox::Skybox(std::string right, std::string top, std::string front, std::string left, std::string bottom, std::string back, diff --git a/src/skybox.h b/src/skybox.h index 7ededd0..654daef 100644 --- a/src/skybox.h +++ b/src/skybox.h @@ -10,39 +10,42 @@ #include #include +#include #include #include #include -#include #include #include +#include -class Skybox : protected QOpenGLFunctions { -public: - // Delegate this constructor to use default skybox images - // + This allows creating a skybox with no arguments ( auto s = new Skybox; ) - explicit Skybox(std::string name="Skybox"); - explicit Skybox(QOpenGLTexture * cubeMap, const std::string & name="Skybox"); - // Constructor, Destructor - Skybox(std::string right, std::string top, std::string front, - std::string left, std::string bottom, std::string back, - const std::string & name="Skybox"); - ~Skybox() {} +namespace Qtk { + class QTKAPI Skybox : protected QOpenGLFunctions { + public: + // Delegate this constructor to use default skybox images + // + This allows creating a skybox with no arguments ( auto s = new Skybox; ) + explicit Skybox(std::string name="Skybox"); + explicit Skybox(QOpenGLTexture * cubeMap, const std::string & name="Skybox"); + // Constructor, Destructor + Skybox(std::string right, std::string top, std::string front, + std::string left, std::string bottom, std::string back, + const std::string & name="Skybox"); + ~Skybox() {} - void draw(); + void draw(); -private: - void init(); + private: + void init(); - Vertices mVertices; - Indices mIndices; + Vertices mVertices; + Indices mIndices; - QOpenGLShaderProgram mProgram; - QOpenGLVertexArrayObject mVAO; - QOpenGLBuffer mVBO; - QOpenGLTexture * mCubeMap; -}; + QOpenGLShaderProgram mProgram; + QOpenGLVertexArrayObject mVAO; + QOpenGLBuffer mVBO; + QOpenGLTexture * mCubeMap; + }; +} #endif // QTK_SKYBOX_H diff --git a/src/texture.cpp b/src/texture.cpp index 3b7cb39..5b3795f 100644 --- a/src/texture.cpp +++ b/src/texture.cpp @@ -11,6 +11,7 @@ #include +using namespace Qtk; QImage * Texture::initImage(const char * image, bool flipX, bool flipY) { diff --git a/src/texture.h b/src/texture.h index bf41dbf..f2eb5aa 100644 --- a/src/texture.h +++ b/src/texture.h @@ -11,32 +11,35 @@ #include +#include -class Texture { -public: - ~Texture() {} +namespace Qtk { + class QTKAPI Texture { + public: + ~Texture() {} - // QImage - static QImage * initImage(const char * image, - bool flipX=false, bool flipY=false); + // QImage + static QImage * initImage(const char * image, + bool flipX=false, bool flipY=false); - // 2D Texture - static QOpenGLTexture * initTexture2D(const char * texture, - bool flipX=false, bool flipY=false); + // 2D Texture + static QOpenGLTexture * initTexture2D(const char * texture, + bool flipX=false, bool flipY=false); - // Cube maps - static QOpenGLTexture * initCubeMap(QImage right, QImage top, - QImage front, QImage left, - QImage bottom, QImage back); - // Overloads for cube map initialization - static QOpenGLTexture * initCubeMap(const char * tile); - static QOpenGLTexture * initCubeMap(const char * right, const char * top, - const char * front, const char * left, - const char * bottom, const char * back); + // Cube maps + static QOpenGLTexture * initCubeMap(QImage right, QImage top, + QImage front, QImage left, + QImage bottom, QImage back); + // Overloads for cube map initialization + static QOpenGLTexture * initCubeMap(const char * tile); + static QOpenGLTexture * initCubeMap(const char * right, const char * top, + const char * front, const char * left, + const char * bottom, const char * back); -private: - // Private ctor to prevent creating instances of this class - Texture() {} -}; + private: + // Private ctor to prevent creating instances of this class + Texture() {} + }; +} #endif // QTOPENGL_TEXTURE_H diff --git a/src/transform3D.cpp b/src/transform3D.cpp index 7fc4b50..9fd3db9 100644 --- a/src/transform3D.cpp +++ b/src/transform3D.cpp @@ -9,6 +9,7 @@ #include +using namespace Qtk; const QVector3D Transform3D::LocalForward(0.0f, 0.0f, 1.0f); const QVector3D Transform3D::LocalUp(0.0f, 1.0f, 0.0f); @@ -110,35 +111,41 @@ QVector3D Transform3D::right() const * QT Streams ******************************************************************************/ -QDebug operator<<(QDebug dbg, const Transform3D & transform) -{ - dbg << "Transform3D\n{\n"; - dbg << "Position: <" << transform.translation().x() << ", " - << transform.translation().y() << ", " - << transform.translation().z() << ">\n"; - dbg << "Scale: <" << transform.scale().x() << ", " - << transform.scale().y() << ", " - << transform.scale().z() << ">\n"; - dbg << "Rotation: <" << transform.rotation().x() << ", " - << transform.rotation().y() << ", " - << transform.rotation().z() << " | " << - transform.rotation().scalar() << ">\n}"; - return dbg; +namespace Qtk { +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug dbg, const Transform3D & transform) + { + dbg << "Transform3D\n{\n"; + dbg << "Position: <" << transform.translation().x() << ", " + << transform.translation().y() << ", " + << transform.translation().z() << ">\n"; + dbg << "Scale: <" << transform.scale().x() << ", " + << transform.scale().y() << ", " + << transform.scale().z() << ">\n"; + dbg << "Rotation: <" << transform.rotation().x() << ", " + << transform.rotation().y() << ", " + << transform.rotation().z() << " | " << + transform.rotation().scalar() << ">\n}"; + return dbg; } +#endif -QDataStream & operator<<(QDataStream & out, const Transform3D & transform) -{ - out << transform.mTranslation; - out << transform.mScale; - out << transform.mRotation; - return out; -} +#ifndef QT_NO_DATASTREAM + QDataStream & operator<<(QDataStream & out, const Transform3D & transform) + { + out << transform.mTranslation; + out << transform.mScale; + out << transform.mRotation; + return out; + } -QDataStream & operator>>(QDataStream & in, Transform3D & transform) -{ - in >> transform.mTranslation; - in >> transform.mScale; - in >> transform.mRotation; - transform.m_dirty = true; - return in; + QDataStream & operator>>(QDataStream & in, Transform3D & transform) + { + in >> transform.mTranslation; + in >> transform.mScale; + in >> transform.mRotation; + transform.m_dirty = true; + return in; + } +#endif } diff --git a/src/transform3D.h b/src/transform3D.h index 2ce6c74..14123b7 100644 --- a/src/transform3D.h +++ b/src/transform3D.h @@ -10,108 +10,116 @@ #ifndef QTK_TRANSFORM3D_H #define QTK_TRANSFORM3D_H -#include #include #include #include +#ifndef QT_NO_DEBUG_STREAM +#include +#endif -class Transform3D -{ -public: - // Constructors - inline Transform3D() : m_dirty(true), - mScale(1.0f, 1.0f, 1.0f), - mTranslation(0.0f, 0.0f, 0.0f) { } +#include - // - // Transformations +namespace Qtk { + 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) - { translate(QVector3D(dx, dy, dz));} + // + // Transformations - // Scale object with multiplication - void scale(const QVector3D & ds); - inline void scale(float dx, float dy, float dz) - { scale(QVector3D(dx, dy, dz));} - inline void scale(float factor) - { scale(QVector3D(factor, factor, factor));} + void translate(const QVector3D & dt); + inline void translate(float dx, float dy, float dz) + { translate(QVector3D(dx, dy, dz));} - // Multiplying by a rotation - void rotate(const QQuaternion & dr); - inline void rotate(float angle, const QVector3D & axis) - { rotate(QQuaternion::fromAxisAndAngle(axis, angle));} - inline void rotate(float angle, float ax, float ay, float az) - { rotate(QQuaternion::fromAxisAndAngle(ax, ay, az, angle));} + // Scale object with multiplication + void scale(const QVector3D & ds); + inline void scale(float dx, float dy, float dz) + { scale(QVector3D(dx, dy, dz));} + inline void scale(float factor) + { scale(QVector3D(factor, factor, factor));} - // Scale object by addition - 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));} + // Multiplying by a rotation + void rotate(const QQuaternion & dr); + inline void rotate(float angle, const QVector3D & axis) + { rotate(QQuaternion::fromAxisAndAngle(axis, angle));} + inline void rotate(float angle, float ax, float ay, float az) + { rotate(QQuaternion::fromAxisAndAngle(ax, ay, az, angle));} - // - // Setters + // Scale object by addition + 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); - inline void setTranslation(float x, float y, float z) - { setTranslation(QVector3D(x, y, z));} + // + // Setters - // Set object scale - void setScale(const QVector3D & s); - inline void setScale(float x, float y, float z) - { setScale(QVector3D(x, y, z));} - inline void setScale(float k) - { setScale(QVector3D(k, k, k));} + // Set object position + void setTranslation(const QVector3D & t); + inline void setTranslation(float x, float y, float z) + { setTranslation(QVector3D(x, y, z));} - // Set object rotation - 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));} + // Set object scale + void setScale(const QVector3D & s); + inline void setScale(float x, float y, float z) + { setScale(QVector3D(x, y, z));} + inline void setScale(float k) + { setScale(QVector3D(k, k, k));} - // - // Accessors + // Set object rotation + 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; } - inline const QQuaternion & rotation() const { return mRotation; } - const QMatrix4x4 & toMatrix(); + // + // Accessors - QVector3D forward() const; - QVector3D up() const; - QVector3D right() const; + inline const QVector3D & translation() const { return mTranslation;} + inline const QVector3D & scale() const { return mScale; } + 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: - QVector3D mTranslation; - QQuaternion mRotation; - QVector3D mScale; - QMatrix4x4 mWorld; + static const QVector3D LocalForward, LocalUp, LocalRight; + + private: + QVector3D mTranslation; + QQuaternion mRotation; + QVector3D mScale; + QMatrix4x4 mWorld; + + bool m_dirty; - bool m_dirty; #ifndef QT_NO_DATASTREAM - friend QDataStream &operator<<(QDataStream & out, const Transform3D & transform); - friend QDataStream &operator>>(QDataStream & in, Transform3D & transform); + friend QDataStream &operator<<(QDataStream & out, const Transform3D & transform); + friend QDataStream &operator>>(QDataStream & in, Transform3D & transform); #endif -}; + }; -Q_DECLARE_TYPEINFO(Transform3D, Q_MOVABLE_TYPE); // Qt Streams #ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug dbg, const Transform3D & transform); + QDebug operator<<(QDebug dbg, const Transform3D & transform); #endif #ifndef QT_NO_DATASTREAM -QDataStream &operator<<(QDataStream & out, const Transform3D & transform); -QDataStream &operator>>(QDataStream & in, Transform3D & transform); + QDataStream &operator<<(QDataStream & out, const Transform3D & transform); + QDataStream &operator>>(QDataStream & in, Transform3D & transform); #endif +} + +Q_DECLARE_TYPEINFO(Qtk::Transform3D, Q_MOVABLE_TYPE); #endif // QTK_TRANSFORM3D_H