Work on adding more doxygen comments #12
@ -1,8 +1,5 @@
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
# clang-format off
 | 
			
		||||
BasedOnStyle: Google
 | 
			
		||||
# clang-format on
 | 
			
		||||
AlignAfterOpenBracket: AlwaysBreak
 | 
			
		||||
AlignArrayOfStructures: Left
 | 
			
		||||
AlignConsecutiveAssignments: None
 | 
			
		||||
 | 
			
		||||
@ -85,7 +85,7 @@ endif()
 | 
			
		||||
set(
 | 
			
		||||
    PUBLIC_HEADERS
 | 
			
		||||
    src/qtkwidget.h
 | 
			
		||||
  src/abstractscene.h
 | 
			
		||||
    src/scene.h
 | 
			
		||||
    src/camera3d.h
 | 
			
		||||
    src/mesh.h
 | 
			
		||||
    src/meshrenderer.h
 | 
			
		||||
@ -99,7 +99,7 @@ set(
 | 
			
		||||
set(
 | 
			
		||||
    SOURCE_FILES
 | 
			
		||||
    src/qtkwidget.cpp
 | 
			
		||||
  src/abstractscene.cpp
 | 
			
		||||
    src/scene.cpp
 | 
			
		||||
    src/camera3d.cpp
 | 
			
		||||
    src/input.cpp
 | 
			
		||||
    src/input.h
 | 
			
		||||
@ -118,7 +118,8 @@ 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
 | 
			
		||||
set_target_properties(
 | 
			
		||||
    qtk-widget PROPERTIES
 | 
			
		||||
    PUBLIC_HEADER "${PUBLIC_HEADERS}"
 | 
			
		||||
    VERSION ${PROJECT_VERSION}
 | 
			
		||||
)
 | 
			
		||||
@ -144,7 +145,8 @@ if(WIN32)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
# Install files
 | 
			
		||||
install(TARGETS qtk-widget
 | 
			
		||||
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
 | 
			
		||||
@ -157,7 +159,8 @@ install(TARGETS qtk-widget
 | 
			
		||||
# 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
 | 
			
		||||
install(
 | 
			
		||||
    EXPORT qtk-export
 | 
			
		||||
    FILE qtkTargets.cmake
 | 
			
		||||
    CONFIGURATIONS Debug|Release
 | 
			
		||||
    DESTINATION ${CMAKE_INSTALL_PREFIX}/cmake
 | 
			
		||||
@ -175,7 +178,8 @@ configure_file(
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# Add our Qt resources.qrc file to our application
 | 
			
		||||
set(QTK_APP_SOURCES app/main.cpp
 | 
			
		||||
set(
 | 
			
		||||
    QTK_APP_SOURCES app/main.cpp
 | 
			
		||||
    app/examplescene.cpp app/examplescene.h
 | 
			
		||||
    app/mainwindow.cpp app/mainwindow.h app/mainwindow.ui
 | 
			
		||||
    app/resourcemanager.h
 | 
			
		||||
@ -189,13 +193,15 @@ target_include_directories(qtk-main PRIVATE src/ app/)
 | 
			
		||||
# Link qtk-main executable to main qtk-widget library
 | 
			
		||||
target_link_libraries(qtk-main PUBLIC qtk-widget)
 | 
			
		||||
 | 
			
		||||
set_target_properties(qtk-main PROPERTIES
 | 
			
		||||
set_target_properties(
 | 
			
		||||
    qtk-main 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-main
 | 
			
		||||
install(
 | 
			
		||||
    TARGETS qtk-main
 | 
			
		||||
    BUNDLE DESTINATION .
 | 
			
		||||
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
 | 
			
		||||
)
 | 
			
		||||
@ -206,7 +212,8 @@ if(WIN32)
 | 
			
		||||
  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
 | 
			
		||||
    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>"
 | 
			
		||||
 | 
			
		||||
@ -6,12 +6,12 @@
 | 
			
		||||
## Contact: shaunrd0@gmail.com  | URL: www.shaunreed.com | GitHub: shaunrd0   ##
 | 
			
		||||
##############################################################################*/
 | 
			
		||||
 | 
			
		||||
#include <abstractscene.h>
 | 
			
		||||
#include <camera3d.h>
 | 
			
		||||
#include <examplescene.h>
 | 
			
		||||
#include <meshrenderer.h>
 | 
			
		||||
#include <model.h>
 | 
			
		||||
#include <resourcemanager.h>
 | 
			
		||||
#include <scene.h>
 | 
			
		||||
#include <texture.h>
 | 
			
		||||
 | 
			
		||||
using namespace Qtk;
 | 
			
		||||
@ -21,8 +21,8 @@ using namespace Qtk;
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
ExampleScene::ExampleScene() {
 | 
			
		||||
  Camera().transform().setTranslation(0.0f, 0.0f, 20.0f);
 | 
			
		||||
  Camera().transform().setRotation(-5.0f, 0.0f, 1.0f, 0.0f);
 | 
			
		||||
  getCamera().getTransform().setTranslation(0.0f, 0.0f, 20.0f);
 | 
			
		||||
  getCamera().getTransform().setRotation(-5.0f, 0.0f, 1.0f, 0.0f);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ExampleScene::~ExampleScene() {
 | 
			
		||||
@ -44,60 +44,40 @@ ExampleScene::~ExampleScene() {
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
void ExampleScene::init() {
 | 
			
		||||
  auto * sb = new Qtk::Skybox("Skybox");
 | 
			
		||||
  setSkybox(sb);
 | 
			
		||||
  setSkybox(new Qtk::Skybox("Skybox"));
 | 
			
		||||
 | 
			
		||||
  // Initialize Phong example 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");
 | 
			
		||||
  //
 | 
			
		||||
  // Create simple shapes using MeshRenderer class and data in mesh.h
 | 
			
		||||
 | 
			
		||||
  // You no longer need to manually bind shader program.
 | 
			
		||||
  // + But, you can still bind it if you want to.
 | 
			
		||||
  //  mTestPhong->bindShaders();
 | 
			
		||||
  mTestPhong->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
 | 
			
		||||
  mTestPhong->setUniform("uLightColor", QVector3D(1.0f, 1.0f, 1.0f));
 | 
			
		||||
  mTestPhong->setUniform("uAmbientStrength", 0.2f);
 | 
			
		||||
  mTestPhong->setUniform("uSpecularStrength", 0.50f);
 | 
			
		||||
  mTestPhong->setUniform("uSpecularShine", 256);
 | 
			
		||||
  mTestPhong->reallocateNormals(mTestPhong->getNormals());
 | 
			
		||||
  //  mTestPhong->releaseShaders();
 | 
			
		||||
  mMeshes.push_back(
 | 
			
		||||
      new Qtk::MeshRenderer("rightTriangle", Triangle(QTK_DRAW_ELEMENTS)));
 | 
			
		||||
  mMeshes.back()->mTransform.setTranslation(-5.0f, 0.0f, -2.0f);
 | 
			
		||||
 | 
			
		||||
  // Initialize Ambient example 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();
 | 
			
		||||
  mTestAmbient->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
 | 
			
		||||
  mTestAmbient->setUniform("uLightColor", QVector3D(1.0f, 1.0f, 1.0f));
 | 
			
		||||
  mTestAmbient->setUniform("uAmbientStrength", 0.2f);
 | 
			
		||||
  mTestAmbient->reallocateNormals(mTestAmbient->getNormals());
 | 
			
		||||
  mMeshes.push_back(
 | 
			
		||||
      new Qtk::MeshRenderer("centerCube", Cube(QTK_DRAW_ELEMENTS)));
 | 
			
		||||
  mMeshes.back()->mTransform.setTranslation(-7.0f, 0.0f, -2.0f);
 | 
			
		||||
 | 
			
		||||
  // Initialize Diffuse example 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();
 | 
			
		||||
  mTestDiffuse->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
 | 
			
		||||
  mTestDiffuse->setUniform("uLightColor", QVector3D(1.0f, 1.0f, 1.0f));
 | 
			
		||||
  mTestDiffuse->setUniform("uAmbientStrength", 0.2f);
 | 
			
		||||
  mTestDiffuse->reallocateNormals(mTestDiffuse->getNormals());
 | 
			
		||||
  mMeshes.push_back(
 | 
			
		||||
      new Qtk::MeshRenderer("leftTriangle", Triangle(QTK_DRAW_ELEMENTS)));
 | 
			
		||||
  mMeshes.back()->mTransform.setTranslation(-9.0f, 0.0f, -2.0f);
 | 
			
		||||
  mMeshes.back()->setDrawType(GL_LINE_LOOP);
 | 
			
		||||
 | 
			
		||||
  // Initialize Specular example 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();
 | 
			
		||||
  mTestSpecular->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
 | 
			
		||||
  mTestSpecular->setUniform("uLightColor", QVector3D(1.0f, 1.0f, 1.0f));
 | 
			
		||||
  mTestSpecular->setUniform("uAmbientStrength", 0.2f);
 | 
			
		||||
  mTestSpecular->setUniform("uSpecularStrength", 0.50f);
 | 
			
		||||
  mTestSpecular->setUniform("uSpecularShine", 256);
 | 
			
		||||
  mTestSpecular->reallocateNormals(mTestSpecular->getNormals());
 | 
			
		||||
  mMeshes.push_back(
 | 
			
		||||
      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 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);
 | 
			
		||||
  // This function changes values we have allocated in a buffer, so init() after
 | 
			
		||||
  mMeshes.back()->setColor(GREEN);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // Model loading
 | 
			
		||||
  // 3D Model loading
 | 
			
		||||
 | 
			
		||||
  mModels.push_back(
 | 
			
		||||
      new Qtk::Model("backpack", ":/models/backpack/backpack.obj"));
 | 
			
		||||
@ -129,18 +109,124 @@ void ExampleScene::init() {
 | 
			
		||||
      new Qtk::Model("masterChief", ":/models/spartan/spartan.obj"));
 | 
			
		||||
  mModels.back()->mTransform.setTranslation(-1.5f, 0.5f, -2.0f);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // Building example mesh objects
 | 
			
		||||
  // Simple cube lighting examples.
 | 
			
		||||
 | 
			
		||||
  // Render an alien with specular
 | 
			
		||||
  // Test alien Model with phong lighting and specular mapping
 | 
			
		||||
  mMeshes.push_back(new Qtk::MeshRenderer(
 | 
			
		||||
      "alienTestLight", Triangle(Qtk::QTK_DRAW_ELEMENTS)));
 | 
			
		||||
  mMeshes.back()->mTransform.setTranslation(4.0f, 1.5f, 10.0f);
 | 
			
		||||
  /* Phong lighting example on a basic cube. */
 | 
			
		||||
  mTestPhong = new Qtk::MeshRenderer("phong", Qtk::Cube());
 | 
			
		||||
  mTestPhong->mTransform.setTranslation(3.0f, 0.0f, -2.0f);
 | 
			
		||||
  // NOTE: You no longer need to manually bind shader program to set uniforms.
 | 
			
		||||
  // + You can still bind it if you want to for performance reasons.
 | 
			
		||||
  // + Qtk will only bind / release if the shader program is not already bound.
 | 
			
		||||
  mTestPhong->setShaders(":/solid-phong.vert", ":/solid-phong.frag");
 | 
			
		||||
 | 
			
		||||
  // For example this would technically not be efficient, because each one of
 | 
			
		||||
  // these calls will bind, set, release. We could instead bind, set N uniforms,
 | 
			
		||||
  // and release when we are finished.
 | 
			
		||||
  //  mTestPhong->bindShaders();
 | 
			
		||||
  mTestPhong->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
 | 
			
		||||
  mTestPhong->setUniform("uLightColor", QVector3D(1.0f, 1.0f, 1.0f));
 | 
			
		||||
  mTestPhong->setUniform("uAmbientStrength", 0.2f);
 | 
			
		||||
  mTestPhong->setUniform("uSpecularStrength", 0.50f);
 | 
			
		||||
  mTestPhong->setUniform("uSpecularShine", 256);
 | 
			
		||||
  //  mTestPhong->releaseShaders();
 | 
			
		||||
  mTestPhong->reallocateNormals(mTestPhong->getNormals());
 | 
			
		||||
  // NOTE: This is only an example and I won't worry about this kind of
 | 
			
		||||
  // efficiency while initializing the following objects.
 | 
			
		||||
 | 
			
		||||
  // Phong lighting example light source. This is just for visual reference.
 | 
			
		||||
  // + We refer to the position of this object in draw() to update lighting.
 | 
			
		||||
  mMeshes.push_back(
 | 
			
		||||
      new Qtk::MeshRenderer("phongLight", Triangle(QTK_DRAW_ELEMENTS)));
 | 
			
		||||
  mMeshes.back()->mTransform.setTranslation(3.0f, 2.0f, -2.0f);
 | 
			
		||||
  mMeshes.back()->mTransform.scale(0.25f);
 | 
			
		||||
  // This function changes values we have allocated in a buffer, so init() after
 | 
			
		||||
  mMeshes.back()->setColor(GREEN);
 | 
			
		||||
 | 
			
		||||
  /* Example of a cube with no lighting applied */
 | 
			
		||||
  mMeshes.push_back(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");
 | 
			
		||||
  mMeshes.back()->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
 | 
			
		||||
  // No light source needed for this lighting technique
 | 
			
		||||
 | 
			
		||||
  /* Initialize Ambient example cube */
 | 
			
		||||
  mTestAmbient = new Qtk::MeshRenderer("ambient", Cube());
 | 
			
		||||
  mTestAmbient->mTransform.setTranslation(7.0f, 0.0f, -2.0f);
 | 
			
		||||
  mTestAmbient->setShaders(":/solid-ambient.vert", ":/solid-ambient.frag");
 | 
			
		||||
  // Changing these uniform values will alter lighting effects.
 | 
			
		||||
  mTestAmbient->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
 | 
			
		||||
  mTestAmbient->setUniform("uLightColor", QVector3D(1.0f, 1.0f, 1.0f));
 | 
			
		||||
  mTestAmbient->setUniform("uAmbientStrength", 0.2f);
 | 
			
		||||
  mTestAmbient->reallocateNormals(mTestAmbient->getNormals());
 | 
			
		||||
  // No light source needed for this lighting technique
 | 
			
		||||
 | 
			
		||||
  /* Initialize Diffuse example 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->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
 | 
			
		||||
  mTestDiffuse->setUniform("uLightColor", QVector3D(1.0f, 1.0f, 1.0f));
 | 
			
		||||
  mTestDiffuse->setUniform("uAmbientStrength", 0.2f);
 | 
			
		||||
  mTestDiffuse->reallocateNormals(mTestDiffuse->getNormals());
 | 
			
		||||
 | 
			
		||||
  // Diffuse lighting example light source. This is just for visual reference.
 | 
			
		||||
  mMeshes.push_back(
 | 
			
		||||
      new Qtk::MeshRenderer("diffuseLight", Triangle(QTK_DRAW_ELEMENTS)));
 | 
			
		||||
  mMeshes.back()->mTransform.setTranslation(9.0f, 2.0f, -2.0f);
 | 
			
		||||
  mMeshes.back()->mTransform.scale(0.25f);
 | 
			
		||||
 | 
			
		||||
  /* Initialize Specular example 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->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
 | 
			
		||||
  mTestSpecular->setUniform("uLightColor", QVector3D(1.0f, 1.0f, 1.0f));
 | 
			
		||||
  mTestSpecular->setUniform("uAmbientStrength", 0.2f);
 | 
			
		||||
  mTestSpecular->setUniform("uSpecularStrength", 0.50f);
 | 
			
		||||
  mTestSpecular->setUniform("uSpecularShine", 256);
 | 
			
		||||
  mTestSpecular->reallocateNormals(mTestSpecular->getNormals());
 | 
			
		||||
 | 
			
		||||
  // Specular lighting example light source. This is just for visual reference.
 | 
			
		||||
  mMeshes.push_back(
 | 
			
		||||
      new Qtk::MeshRenderer("specularLight", Triangle(QTK_DRAW_ELEMENTS)));
 | 
			
		||||
  mMeshes.back()->mTransform.setTranslation(11.0f, 2.0f, -2.0f);
 | 
			
		||||
  mMeshes.back()->mTransform.scale(0.25f);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  /* Test basic cube with phong.vert and phong.frag shaders */
 | 
			
		||||
  mMeshes.push_back(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");
 | 
			
		||||
  // WARNING: Set color before reallocating normals.
 | 
			
		||||
  mMeshes.back()->setColor(QVector3D(0.0f, 0.25f, 0.0f));
 | 
			
		||||
  mMeshes.back()->reallocateNormals(mMeshes.back()->getNormals());
 | 
			
		||||
 | 
			
		||||
  mMeshes.back()->setUniform("uMaterial.ambient", QVector3D(0.0f, 0.3f, 0.0f));
 | 
			
		||||
  mMeshes.back()->setUniform("uMaterial.diffuse", QVector3D(0.0f, 0.2f, 0.0f));
 | 
			
		||||
  mMeshes.back()->setUniform("uMaterial.specular", QVector3D(1.0f, 1.0f, 1.0f));
 | 
			
		||||
  mMeshes.back()->setUniform("uMaterial.ambientStrength", 1.0f);
 | 
			
		||||
  mMeshes.back()->setUniform("uMaterial.diffuseStrength", 1.0f);
 | 
			
		||||
  mMeshes.back()->setUniform("uMaterial.specularStrength", 1.0f);
 | 
			
		||||
  mMeshes.back()->setUniform("uMaterial.shine", 64.0f);
 | 
			
		||||
  mMeshes.back()->setUniform("uLight.ambient", QVector3D(0.25f, 0.2f, 0.075f));
 | 
			
		||||
  mMeshes.back()->setUniform("uLight.diffuse", QVector3D(0.75f, 0.6f, 0.22f));
 | 
			
		||||
  mMeshes.back()->setUniform("uLight.specular", QVector3D(0.62f, 0.55f, 0.37f));
 | 
			
		||||
  mMeshes.back()->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
 | 
			
		||||
 | 
			
		||||
  // Light source for testPhong cube
 | 
			
		||||
  mMeshes.push_back(
 | 
			
		||||
      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);
 | 
			
		||||
  mMeshes.back()->setColor(RED);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // Building more complex objects for showing examples of lighting techniques
 | 
			
		||||
 | 
			
		||||
  /* Test alien Model with phong lighting and specular mapping. */
 | 
			
		||||
  mModels.push_back(new Qtk::Model(
 | 
			
		||||
      "alienTest", ":/models/alien-hominid/alien.obj", ":/model-specular.vert",
 | 
			
		||||
      ":/model-specular.frag"));
 | 
			
		||||
@ -158,14 +244,15 @@ void ExampleScene::init() {
 | 
			
		||||
  mModels.back()->setUniform("uLight.diffuse", QVector3D(1.0f, 1.0f, 1.0f));
 | 
			
		||||
  mModels.back()->setUniform("uLight.specular", QVector3D(1.0f, 1.0f, 1.0f));
 | 
			
		||||
 | 
			
		||||
  // Test spartan Model with phong lighting, specular and normal mapping
 | 
			
		||||
  mMeshes.push_back(
 | 
			
		||||
      new Qtk::MeshRenderer("spartanTestLight", Triangle(QTK_DRAW_ELEMENTS)));
 | 
			
		||||
  mMeshes.back()->mTransform.setTranslation(1.0f, 1.5f, 10.0f);
 | 
			
		||||
  // Light source for alienTest object.
 | 
			
		||||
  mMeshes.push_back(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
 | 
			
		||||
  mMeshes.back()->setColor(GREEN);
 | 
			
		||||
 | 
			
		||||
  /* Test spartan Model with phong lighting, specular and normal mapping. */
 | 
			
		||||
  mModels.push_back(new Qtk::Model(
 | 
			
		||||
      "spartanTest", ":/models/spartan/spartan.obj", ":/model-normals.vert",
 | 
			
		||||
      ":/model-normals.frag"));
 | 
			
		||||
@ -182,65 +269,17 @@ void ExampleScene::init() {
 | 
			
		||||
  mModels.back()->setUniform("uLight.diffuse", QVector3D(1.0f, 1.0f, 1.0f));
 | 
			
		||||
  mModels.back()->setUniform("uLight.specular", QVector3D(1.0f, 1.0f, 1.0f));
 | 
			
		||||
 | 
			
		||||
  // Test basic cube with phong.vert and phong.frag shaders
 | 
			
		||||
  // Light source for spartanTest object.
 | 
			
		||||
  mMeshes.push_back(
 | 
			
		||||
      new Qtk::MeshRenderer("testLight", Triangle(QTK_DRAW_ELEMENTS)));
 | 
			
		||||
  mMeshes.back()->mTransform.setTranslation(5.0f, 1.25f, 10.0f);
 | 
			
		||||
      new Qtk::MeshRenderer("spartanTestLight", Triangle(QTK_DRAW_ELEMENTS)));
 | 
			
		||||
  mMeshes.back()->mTransform.setTranslation(1.0f, 1.5f, 10.0f);
 | 
			
		||||
  mMeshes.back()->mTransform.scale(0.25f);
 | 
			
		||||
  mMeshes.back()->setDrawType(GL_LINE_LOOP);
 | 
			
		||||
  // This function changes values we have allocated in a buffer, so init() after
 | 
			
		||||
  mMeshes.back()->setColor(GREEN);
 | 
			
		||||
 | 
			
		||||
  mMeshes.push_back(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));
 | 
			
		||||
  mMeshes.back()->reallocateNormals(mMeshes.back()->getNormals());
 | 
			
		||||
 | 
			
		||||
  mMeshes.back()->setUniform("uMaterial.ambient", QVector3D(0.0f, 0.3f, 0.0f));
 | 
			
		||||
  mMeshes.back()->setUniform("uMaterial.diffuse", QVector3D(0.0f, 0.2f, 0.0f));
 | 
			
		||||
  mMeshes.back()->setUniform("uMaterial.specular", QVector3D(1.0f, 1.0f, 1.0f));
 | 
			
		||||
  mMeshes.back()->setUniform("uMaterial.ambientStrength", 1.0f);
 | 
			
		||||
  mMeshes.back()->setUniform("uMaterial.diffuseStrength", 1.0f);
 | 
			
		||||
  mMeshes.back()->setUniform("uMaterial.specularStrength", 1.0f);
 | 
			
		||||
  mMeshes.back()->setUniform("uMaterial.shine", 64.0f);
 | 
			
		||||
  mMeshes.back()->setUniform("uLight.ambient", QVector3D(0.25f, 0.2f, 0.075f));
 | 
			
		||||
  mMeshes.back()->setUniform("uLight.diffuse", QVector3D(0.75f, 0.6f, 0.22f));
 | 
			
		||||
  mMeshes.back()->setUniform("uLight.specular", QVector3D(0.62f, 0.55f, 0.37f));
 | 
			
		||||
  mMeshes.back()->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // Create simple shapes using MeshRenderer class and data in mesh.h
 | 
			
		||||
 | 
			
		||||
  mMeshes.push_back(
 | 
			
		||||
      new Qtk::MeshRenderer("rightTriangle", Triangle(QTK_DRAW_ELEMENTS)));
 | 
			
		||||
  mMeshes.back()->mTransform.setTranslation(-5.0f, 0.0f, -2.0f);
 | 
			
		||||
 | 
			
		||||
  mMeshes.push_back(
 | 
			
		||||
      new Qtk::MeshRenderer("centerCube", Cube(QTK_DRAW_ELEMENTS)));
 | 
			
		||||
  mMeshes.back()->mTransform.setTranslation(-7.0f, 0.0f, -2.0f);
 | 
			
		||||
 | 
			
		||||
  mMeshes.push_back(
 | 
			
		||||
      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 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 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);
 | 
			
		||||
  // This function changes values we have allocated in a buffer, so init() after
 | 
			
		||||
  mMeshes.back()->setColor(GREEN);
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // Testing for normals, texture coordinates
 | 
			
		||||
  // Test drawing simple geometry with various OpenGL drawing modes
 | 
			
		||||
 | 
			
		||||
  // RGB Normals cube to show normals are correct with QTK_DRAW_ARRAYS
 | 
			
		||||
  mMeshes.push_back(
 | 
			
		||||
@ -345,35 +384,11 @@ void ExampleScene::init() {
 | 
			
		||||
  mMeshes.back()->setTexture(":/crate.png");
 | 
			
		||||
  mMeshes.back()->setUniform("uTexture", 0);
 | 
			
		||||
  mMeshes.back()->reallocateTexCoords(mMeshes.back()->getTexCoords());
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // Lighting cube examples
 | 
			
		||||
 | 
			
		||||
  // Example of a cube with no lighting applied
 | 
			
		||||
  mMeshes.push_back(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");
 | 
			
		||||
  mMeshes.back()->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
 | 
			
		||||
 | 
			
		||||
  // Create objects that represent light sources for lighting examples
 | 
			
		||||
  mMeshes.push_back(
 | 
			
		||||
      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 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 Qtk::MeshRenderer("specularLight", Triangle(QTK_DRAW_ELEMENTS)));
 | 
			
		||||
  mMeshes.back()->mTransform.setTranslation(11.0f, 2.0f, -2.0f);
 | 
			
		||||
  mMeshes.back()->mTransform.scale(0.25f);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ExampleScene::draw() {
 | 
			
		||||
  // WARNING: We must call the base class draw() function first.
 | 
			
		||||
  // + This will handle rendering core scene components like the Skybox.
 | 
			
		||||
  Scene::draw();
 | 
			
		||||
 | 
			
		||||
  for(const auto & model : mModels) {
 | 
			
		||||
@ -392,13 +407,15 @@ void ExampleScene::draw() {
 | 
			
		||||
      "uLightPosition",
 | 
			
		||||
      MeshRenderer::getInstance("phongLight")->mTransform.getTranslation());
 | 
			
		||||
  mTestPhong->setUniform(
 | 
			
		||||
      "uCameraPosition", ExampleScene::Camera().transform().getTranslation());
 | 
			
		||||
      "uCameraPosition",
 | 
			
		||||
      ExampleScene::getCamera().getTransform().getTranslation());
 | 
			
		||||
  mTestPhong->releaseShaders();
 | 
			
		||||
  mTestPhong->draw();
 | 
			
		||||
 | 
			
		||||
  mTestAmbient->bindShaders();
 | 
			
		||||
  mTestAmbient->setUniform(
 | 
			
		||||
      "uCameraPosition", ExampleScene::Camera().transform().getTranslation());
 | 
			
		||||
      "uCameraPosition",
 | 
			
		||||
      ExampleScene::getCamera().getTransform().getTranslation());
 | 
			
		||||
  mTestAmbient->releaseShaders();
 | 
			
		||||
  mTestAmbient->draw();
 | 
			
		||||
 | 
			
		||||
@ -410,7 +427,8 @@ void ExampleScene::draw() {
 | 
			
		||||
      "uLightPosition",
 | 
			
		||||
      MeshRenderer::getInstance("diffuseLight")->mTransform.getTranslation());
 | 
			
		||||
  mTestDiffuse->setUniform(
 | 
			
		||||
      "uCameraPosition", ExampleScene::Camera().transform().getTranslation());
 | 
			
		||||
      "uCameraPosition",
 | 
			
		||||
      ExampleScene::getCamera().getTransform().getTranslation());
 | 
			
		||||
  mTestDiffuse->releaseShaders();
 | 
			
		||||
  mTestDiffuse->draw();
 | 
			
		||||
 | 
			
		||||
@ -422,7 +440,8 @@ void ExampleScene::draw() {
 | 
			
		||||
      "uLightPosition",
 | 
			
		||||
      MeshRenderer::getInstance("specularLight")->mTransform.getTranslation());
 | 
			
		||||
  mTestSpecular->setUniform(
 | 
			
		||||
      "uCameraPosition", ExampleScene::Camera().transform().getTranslation());
 | 
			
		||||
      "uCameraPosition",
 | 
			
		||||
      ExampleScene::getCamera().getTransform().getTranslation());
 | 
			
		||||
  mTestSpecular->releaseShaders();
 | 
			
		||||
  mTestSpecular->draw();
 | 
			
		||||
}
 | 
			
		||||
@ -433,12 +452,13 @@ void ExampleScene::update() {
 | 
			
		||||
  auto alien = Model::getInstance("alienTest");
 | 
			
		||||
  alien->setUniform("uLight.position", position);
 | 
			
		||||
  alien->setUniform(
 | 
			
		||||
      "uCameraPosition", ExampleScene::Camera().transform().getTranslation());
 | 
			
		||||
      "uCameraPosition",
 | 
			
		||||
      ExampleScene::getCamera().getTransform().getTranslation());
 | 
			
		||||
  auto posMatrix = alien->mTransform.toMatrix();
 | 
			
		||||
  alien->setUniform("uMVP.normalMatrix", posMatrix.normalMatrix());
 | 
			
		||||
  alien->setUniform("uMVP.model", posMatrix);
 | 
			
		||||
  alien->setUniform("uMVP.view", ExampleScene::Camera().toMatrix());
 | 
			
		||||
  alien->setUniform("uMVP.projection", ExampleScene::Projection());
 | 
			
		||||
  alien->setUniform("uMVP.view", ExampleScene::getCamera().toMatrix());
 | 
			
		||||
  alien->setUniform("uMVP.projection", ExampleScene::getProjectionMatrix());
 | 
			
		||||
  alien->mTransform.rotate(0.75f, 0.0f, 1.0f, 0.0f);
 | 
			
		||||
 | 
			
		||||
  position = MeshRenderer::getInstance("spartanTestLight")
 | 
			
		||||
@ -446,12 +466,13 @@ void ExampleScene::update() {
 | 
			
		||||
  auto spartan = Model::getInstance("spartanTest");
 | 
			
		||||
  spartan->setUniform("uLight.position", position);
 | 
			
		||||
  spartan->setUniform(
 | 
			
		||||
      "uCameraPosition", ExampleScene::Camera().transform().getTranslation());
 | 
			
		||||
      "uCameraPosition",
 | 
			
		||||
      ExampleScene::getCamera().getTransform().getTranslation());
 | 
			
		||||
  posMatrix = spartan->mTransform.toMatrix();
 | 
			
		||||
  spartan->setUniform("uMVP.normalMatrix", posMatrix.normalMatrix());
 | 
			
		||||
  spartan->setUniform("uMVP.model", posMatrix);
 | 
			
		||||
  spartan->setUniform("uMVP.view", ExampleScene::Camera().toMatrix());
 | 
			
		||||
  spartan->setUniform("uMVP.projection", ExampleScene::Projection());
 | 
			
		||||
  spartan->setUniform("uMVP.view", ExampleScene::getCamera().toMatrix());
 | 
			
		||||
  spartan->setUniform("uMVP.projection", ExampleScene::getProjectionMatrix());
 | 
			
		||||
  spartan->mTransform.rotate(0.75f, 0.0f, 1.0f, 0.0f);
 | 
			
		||||
 | 
			
		||||
  auto phong = MeshRenderer::getInstance("testPhong");
 | 
			
		||||
@ -461,12 +482,13 @@ void ExampleScene::update() {
 | 
			
		||||
      MeshRenderer::getInstance("testLight")->mTransform.getTranslation();
 | 
			
		||||
  phong->setUniform("uLight.position", position);
 | 
			
		||||
  phong->setUniform(
 | 
			
		||||
      "uCameraPosition", ExampleScene::Camera().transform().getTranslation());
 | 
			
		||||
      "uCameraPosition",
 | 
			
		||||
      ExampleScene::getCamera().getTransform().getTranslation());
 | 
			
		||||
  posMatrix = phong->mTransform.toMatrix();
 | 
			
		||||
  phong->setUniform("uMVP.normalMatrix", posMatrix.normalMatrix());
 | 
			
		||||
  phong->setUniform("uMVP.model", posMatrix);
 | 
			
		||||
  phong->setUniform("uMVP.view", ExampleScene::Camera().toMatrix());
 | 
			
		||||
  phong->setUniform("uMVP.projection", ExampleScene::Projection());
 | 
			
		||||
  phong->setUniform("uMVP.view", ExampleScene::getCamera().toMatrix());
 | 
			
		||||
  phong->setUniform("uMVP.projection", ExampleScene::getProjectionMatrix());
 | 
			
		||||
  phong->releaseShaders();
 | 
			
		||||
 | 
			
		||||
  // Rotate lighting example cubes
 | 
			
		||||
 | 
			
		||||
@ -9,22 +9,65 @@
 | 
			
		||||
#ifndef QTK_EXAMPLE_SCENE_H
 | 
			
		||||
#define QTK_EXAMPLE_SCENE_H
 | 
			
		||||
 | 
			
		||||
#include <abstractscene.h>
 | 
			
		||||
#include <camera3d.h>
 | 
			
		||||
#include <scene.h>
 | 
			
		||||
#include <skybox.h>
 | 
			
		||||
 | 
			
		||||
#include <QMatrix4x4>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Example scene using QtkWidget to render 3D models and simple geometry within
 | 
			
		||||
 * QtOpenGLWidgets. This scene also shows some examples of using GLSL shaders to
 | 
			
		||||
 * apply the basic lighting techniques leading up to Phong.
 | 
			
		||||
 *
 | 
			
		||||
 * The Qtk::Scene base class provides containers for N pointers to MeshRenderer
 | 
			
		||||
 * and Model objects. We can create and insert as many as we like within this
 | 
			
		||||
 * child class implementation. This child class does not need to manually draw
 | 
			
		||||
 * objects inserted into these containers. The child class would only need to
 | 
			
		||||
 * update uniform or other data that may change per-frame.
 | 
			
		||||
 * See scene.h and `init()` for more information.
 | 
			
		||||
 *
 | 
			
		||||
 * To modify the scene objects should be initialized within the `init()` public
 | 
			
		||||
 * method. Any required movement or updates should be applied within `draw()` or
 | 
			
		||||
 * `update()`.
 | 
			
		||||
 *
 | 
			
		||||
 * To create your own Scene from scratch see Qtk::Scene.
 | 
			
		||||
 */
 | 
			
		||||
class ExampleScene : public Qtk::Scene {
 | 
			
		||||
  public:
 | 
			
		||||
    /***************************************************************************
 | 
			
		||||
     * Contructors / Destructors
 | 
			
		||||
     **************************************************************************/
 | 
			
		||||
 | 
			
		||||
    ExampleScene();
 | 
			
		||||
    ~ExampleScene();
 | 
			
		||||
 | 
			
		||||
    /***************************************************************************
 | 
			
		||||
     * Inherited Public Overrides
 | 
			
		||||
     **************************************************************************/
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Initialize objects within the scene
 | 
			
		||||
     */
 | 
			
		||||
    void init() override;
 | 
			
		||||
    /**
 | 
			
		||||
     * Called when OpenGL repaints the widget.
 | 
			
		||||
     */
 | 
			
		||||
    void draw() override;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called when the Qt `frameSwapped` signal is caught.
 | 
			
		||||
     * See definition of `QtkWidget::initializeGL()`
 | 
			
		||||
     */
 | 
			
		||||
    void update() override;
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    /***************************************************************************
 | 
			
		||||
     * Private Members
 | 
			
		||||
     **************************************************************************/
 | 
			
		||||
 | 
			
		||||
    // Additional example objects created within this example.
 | 
			
		||||
    // + The base class Scene manages objects stored within mMeshes or mModels
 | 
			
		||||
    Qtk::MeshRenderer * mTestPhong {};
 | 
			
		||||
    Qtk::MeshRenderer * mTestSpecular {};
 | 
			
		||||
    Qtk::MeshRenderer * mTestDiffuse {};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										14
									
								
								app/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								app/main.cpp
									
									
									
									
									
								
							@ -16,20 +16,6 @@
 | 
			
		||||
int main(int argc, char * argv[]) {
 | 
			
		||||
  QApplication a(argc, argv);
 | 
			
		||||
 | 
			
		||||
  // Set OpenGL Version information
 | 
			
		||||
  // Note: This format must be set before show() is called.
 | 
			
		||||
  QSurfaceFormat format;
 | 
			
		||||
  format.setRenderableType(QSurfaceFormat::OpenGL);
 | 
			
		||||
  format.setProfile(QSurfaceFormat::CoreProfile);
 | 
			
		||||
  format.setVersion(4, 5);
 | 
			
		||||
  // Set the number of samples used for glEnable(GL_MULTISAMPLING)
 | 
			
		||||
  format.setSamples(4);
 | 
			
		||||
  // Set the size of the depth bufer for glEnable(GL_DEPTH_TEST)
 | 
			
		||||
  format.setDepthBufferSize(16);
 | 
			
		||||
#ifdef QTK_DEBUG
 | 
			
		||||
  format.setOption(QSurfaceFormat::DebugContext);
 | 
			
		||||
#endif  // QTK_DEBUG
 | 
			
		||||
 | 
			
		||||
  // Create window for Qt application using custom mainwindow.h
 | 
			
		||||
  MainWindow w;
 | 
			
		||||
  w.show();
 | 
			
		||||
 | 
			
		||||
@ -1,22 +1,37 @@
 | 
			
		||||
/*##############################################################################
 | 
			
		||||
## Author: Shaun Reed                                                         ##
 | 
			
		||||
## Legal: All Content (c) 2022 Shaun Reed, all rights reserved                ##
 | 
			
		||||
## About: MainWindow for creating an example Qt application using QtkWidget   ##
 | 
			
		||||
##                                                                            ##
 | 
			
		||||
## Contact: shaunrd0@gmail.com  | URL: www.shaunreed.com | GitHub: shaunrd0   ##
 | 
			
		||||
##############################################################################*/
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
  ui->setupUi(this);
 | 
			
		||||
 | 
			
		||||
  // Find all QtkWidgets in this QMainWindow and initialize their scenes.
 | 
			
		||||
  for(const auto widget : ui->qWidget->children()) {
 | 
			
		||||
    auto qtkWidget = dynamic_cast<Qtk::QtkWidget *>(widget);
 | 
			
		||||
    if(qtkWidget != nullptr) {
 | 
			
		||||
      std::string key = qtkWidget->objectName().toStdString();
 | 
			
		||||
      // Initialize each scene into a map if it doesn't exist.
 | 
			
		||||
      if(mScenes[key] == nullptr) {
 | 
			
		||||
        mScenes[qtkWidget->objectName().toStdString()] = new ExampleScene();
 | 
			
		||||
        mScenes[key] = new ExampleScene();
 | 
			
		||||
      }
 | 
			
		||||
      qtkWidget->setScene(mScenes[qtkWidget->objectName().toStdString()]);
 | 
			
		||||
      // Set the QtkWidget to use the scene associated with this widget.
 | 
			
		||||
      qtkWidget->setScene(mScenes[key]);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Set the window icon used for Qtk.
 | 
			
		||||
  // TODO: Update this to be something other than kilroy.
 | 
			
		||||
  setWindowIcon(QIcon("../resources/icon.png"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,11 @@
 | 
			
		||||
/*##############################################################################
 | 
			
		||||
## Author: Shaun Reed                                                         ##
 | 
			
		||||
## Legal: All Content (c) 2022 Shaun Reed, all rights reserved                ##
 | 
			
		||||
## About: MainWindow for creating an example Qt application using QtkWidget   ##
 | 
			
		||||
##                                                                            ##
 | 
			
		||||
## Contact: shaunrd0@gmail.com  | URL: www.shaunreed.com | GitHub: shaunrd0   ##
 | 
			
		||||
##############################################################################*/
 | 
			
		||||
 | 
			
		||||
#ifndef MAINWINDOW_H
 | 
			
		||||
#define MAINWINDOW_H
 | 
			
		||||
 | 
			
		||||
@ -12,16 +20,32 @@ namespace Ui {
 | 
			
		||||
  class MainWindow;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class QTK_WIDGET_EXPORT MainWindow
 | 
			
		||||
 | 
			
		||||
    : public QMainWindow {
 | 
			
		||||
/**
 | 
			
		||||
 * MainWindow class to provide an example of using a QtkWidget within a Qt
 | 
			
		||||
 * window application.
 | 
			
		||||
 */
 | 
			
		||||
class QTK_WIDGET_EXPORT MainWindow : public QMainWindow {
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
    /***************************************************************************
 | 
			
		||||
     * Contructors / Destructors
 | 
			
		||||
     **************************************************************************/
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * This ctor also initializes the Scene for each QtkWidget in the window.
 | 
			
		||||
     * To load a different scene this would need to be updated.
 | 
			
		||||
     *
 | 
			
		||||
     * @param parent The parent for this QMainWindow
 | 
			
		||||
     */
 | 
			
		||||
    explicit MainWindow(QWidget * parent = nullptr);
 | 
			
		||||
    ~MainWindow() override;
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    /***************************************************************************
 | 
			
		||||
     * Private Members
 | 
			
		||||
     **************************************************************************/
 | 
			
		||||
 | 
			
		||||
    Ui::MainWindow * ui {};
 | 
			
		||||
    std::unordered_map<std::string, Qtk::Scene *> mScenes {};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -13,6 +13,19 @@
 | 
			
		||||
#ifndef QTK_RESOURCEMANAGER_H
 | 
			
		||||
#define QTK_RESOURCEMANAGER_H
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ResourceManager class used to construct absolute paths to files within the Qt
 | 
			
		||||
 * resources path. There is no need to manually call this method.
 | 
			
		||||
 * Model::loadModel(...) will use this method if a Qt resource path is provided.
 | 
			
		||||
 * The Model constructor behaves the same. If a path is prefixed with `:/` this
 | 
			
		||||
 * static method will be used to resolve a full system path.
 | 
			
		||||
 *
 | 
			
		||||
 * This will likely be deprecated. It has a single call site and it is not
 | 
			
		||||
 * meant for public use. It is public only for convenience.
 | 
			
		||||
 *
 | 
			
		||||
 * RM::getPath(":/models/alien-hominid/alien.obj") =
 | 
			
		||||
 *      /full/path/to/models/alien-hominid/alien.obj
 | 
			
		||||
 */
 | 
			
		||||
typedef class ResourceManager {
 | 
			
		||||
  public:
 | 
			
		||||
    /**
 | 
			
		||||
@ -24,7 +37,7 @@ typedef class ResourceManager {
 | 
			
		||||
     * ':/models/backpack/backpack.obj' An asset at location
 | 
			
		||||
     * qtk/resources/path/to/asset.obj Should be given in qrc format:
 | 
			
		||||
     * ':/path/to/asset.obj'
 | 
			
		||||
     * @return Absoulte system path to a qtk asset
 | 
			
		||||
     * @return Absolute system path to a qtk asset
 | 
			
		||||
     */
 | 
			
		||||
    static std::string getPath(const std::string & path) {
 | 
			
		||||
      // Only construct qtk resource path if in qrc format; else return it as-is
 | 
			
		||||
 | 
			
		||||
@ -1,56 +0,0 @@
 | 
			
		||||
/*##############################################################################
 | 
			
		||||
## 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 {};
 | 
			
		||||
  };
 | 
			
		||||
}  // namespace Qtk
 | 
			
		||||
 | 
			
		||||
#endif  // QTK_SCENE_H
 | 
			
		||||
@ -32,22 +32,22 @@ const QMatrix4x4 & Camera3D::toMatrix() {
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
QDataStream & operator<<(QDataStream & out, Camera3D & transform) {
 | 
			
		||||
  out << transform.transform();
 | 
			
		||||
  out << transform.getTransform();
 | 
			
		||||
  return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QDataStream & operator>>(QDataStream & in, Camera3D & transform) {
 | 
			
		||||
  in >> transform.transform();
 | 
			
		||||
  in >> transform.getTransform();
 | 
			
		||||
  return in;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QDebug operator<<(QDebug dbg, const Camera3D & transform) {
 | 
			
		||||
  dbg << "Camera3D\n{\n";
 | 
			
		||||
  dbg << "Position: <" << transform.translation().x() << ", "
 | 
			
		||||
      << transform.translation().y() << ", " << transform.translation().z()
 | 
			
		||||
      << ">\n";
 | 
			
		||||
  dbg << "Rotation: <" << transform.rotation().x() << ", "
 | 
			
		||||
      << transform.rotation().y() << ", " << transform.rotation().z() << " | "
 | 
			
		||||
      << transform.rotation().scalar() << ">\n}";
 | 
			
		||||
  dbg << "Position: <" << transform.getTranslation().x() << ", "
 | 
			
		||||
      << transform.getTranslation().y() << ", "
 | 
			
		||||
      << transform.getTranslation().z() << ">\n";
 | 
			
		||||
  dbg << "Rotation: <" << transform.getRotation().x() << ", "
 | 
			
		||||
      << transform.getRotation().y() << ", " << transform.getRotation().z()
 | 
			
		||||
      << " | " << transform.getRotation().scalar() << ">\n}";
 | 
			
		||||
  return dbg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -17,19 +17,25 @@
 | 
			
		||||
namespace Qtk {
 | 
			
		||||
  class QTKAPI Camera3D {
 | 
			
		||||
    public:
 | 
			
		||||
      // Constants
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Constants
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      static const QVector3D LocalForward;
 | 
			
		||||
      static const QVector3D LocalUp;
 | 
			
		||||
      static const QVector3D LocalRight;
 | 
			
		||||
 | 
			
		||||
      // Accessors
 | 
			
		||||
      inline Transform3D & transform() { return mTransform; }
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Accessors
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      [[nodiscard]] inline const QVector3D & translation() const {
 | 
			
		||||
      inline Transform3D & getTransform() { return mTransform; }
 | 
			
		||||
 | 
			
		||||
      [[nodiscard]] inline const QVector3D & getTranslation() const {
 | 
			
		||||
        return mTransform.getTranslation();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      [[nodiscard]] inline const QQuaternion & rotation() const {
 | 
			
		||||
      [[nodiscard]] inline const QQuaternion & getRotation() const {
 | 
			
		||||
        return mTransform.getRotation();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@ -49,9 +55,17 @@ namespace Qtk {
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Private Members
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      Transform3D mTransform;
 | 
			
		||||
      QMatrix4x4 mWorld;
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Private Methods
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef QT_NO_DATASTREAM
 | 
			
		||||
      friend QDataStream & operator<<(QDataStream & out, Camera3D & transform);
 | 
			
		||||
      friend QDataStream & operator>>(QDataStream & in, Camera3D & transform);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										17
									
								
								src/input.h
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								src/input.h
									
									
									
									
									
								
							@ -17,10 +17,15 @@
 | 
			
		||||
 | 
			
		||||
namespace Qtk {
 | 
			
		||||
  class QTKAPI Input {
 | 
			
		||||
    public:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Typedefs
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
      friend class Qtk::QtkWidget;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
      // Possible key states
 | 
			
		||||
      /**
 | 
			
		||||
       * Possible key states
 | 
			
		||||
       */
 | 
			
		||||
      enum InputState {
 | 
			
		||||
        InputInvalid,
 | 
			
		||||
        InputRegistered,
 | 
			
		||||
@ -30,6 +35,10 @@ namespace Qtk {
 | 
			
		||||
        InputReleased
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Public Methods
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      // State checking
 | 
			
		||||
      inline static bool keyTriggered(Qt::Key key) {
 | 
			
		||||
        return keyState(key) == InputTriggered;
 | 
			
		||||
@ -63,6 +72,10 @@ namespace Qtk {
 | 
			
		||||
      static QPoint mouseDelta();
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Private Methods
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      // State updating
 | 
			
		||||
      static void update();
 | 
			
		||||
      static void registerKeyPress(int key);
 | 
			
		||||
 | 
			
		||||
@ -1,75 +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 OpenGLTextureFactory;
 | 
			
		||||
 | 
			
		||||
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) override;
 | 
			
		||||
    void keyReleaseEvent(QKeyEvent * event) override;
 | 
			
		||||
    void mousePressEvent(QMouseEvent * event) override;
 | 
			
		||||
    void mouseReleaseEvent(QMouseEvent * event) override;
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    // Private helpers
 | 
			
		||||
    void initializeWidget();
 | 
			
		||||
    void printContextInformation();
 | 
			
		||||
    void updateCameraInput();
 | 
			
		||||
 | 
			
		||||
    Scene * mScene;
 | 
			
		||||
    Object * mObject;
 | 
			
		||||
 | 
			
		||||
    QOpenGLDebugLogger * mDebugLogger;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif  // QTK_MAINWIDGET_H
 | 
			
		||||
							
								
								
									
										38
									
								
								src/mesh.h
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								src/mesh.h
									
									
									
									
									
								
							@ -84,13 +84,26 @@ namespace Qtk {
 | 
			
		||||
  typedef std::vector<QVector2D> TexCoords;
 | 
			
		||||
  typedef std::vector<QVector3D> Normals;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The OpenGL draw mode to initialize QTK shape data for.
 | 
			
		||||
   * Different draw modes require different organization of data.
 | 
			
		||||
   * This enum allows us to predefine simple geometry for different draw modes.
 | 
			
		||||
   */
 | 
			
		||||
  enum DrawMode {
 | 
			
		||||
    QTK_DRAW_ARRAYS,
 | 
			
		||||
    QTK_DRAW_ELEMENTS,
 | 
			
		||||
    QTK_DRAW_ELEMENTS_NORMALS
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Base class for all simple shape objects.
 | 
			
		||||
   */
 | 
			
		||||
  struct QTKAPI ShapeBase {
 | 
			
		||||
    public:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Constructors / Destructors
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      explicit ShapeBase(
 | 
			
		||||
          DrawMode mode = QTK_DRAW_ARRAYS, Vertices v = {}, Indices i = {},
 | 
			
		||||
          Colors c = {}, TexCoords t = {}, Normals n = {}) :
 | 
			
		||||
@ -99,6 +112,10 @@ namespace Qtk {
 | 
			
		||||
          mIndices(std::move(i)), mTexCoords(std::move(t)),
 | 
			
		||||
          mNormals(std::move(n)) {}
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Accessors
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      [[nodiscard]] inline const Vertices & getVertices() const {
 | 
			
		||||
        return mVertices;
 | 
			
		||||
      }
 | 
			
		||||
@ -122,6 +139,10 @@ namespace Qtk {
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    protected:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Protected Members
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      DrawMode mDrawMode;
 | 
			
		||||
 | 
			
		||||
      Vertices mVertices {};
 | 
			
		||||
@ -132,13 +153,26 @@ namespace Qtk {
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  struct Shape : public ShapeBase {
 | 
			
		||||
    public:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Typedefs
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      friend MeshRenderer;
 | 
			
		||||
      friend Object;
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Constructors / Destructors
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      Shape() = default;
 | 
			
		||||
 | 
			
		||||
      explicit Shape(const ShapeBase & rhs) : ShapeBase(rhs) {}
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Setters
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      virtual inline void setVertices(const Vertices & value) {
 | 
			
		||||
        mVertices = value;
 | 
			
		||||
      }
 | 
			
		||||
@ -160,13 +194,15 @@ namespace Qtk {
 | 
			
		||||
      virtual inline void setShape(const Shape & value) { *this = value; }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // Primitives inherit from ShapeBase, does not allow setting of shape values
 | 
			
		||||
  /* Primitives inherit from ShapeBase, doesn't allow setting shape values. */
 | 
			
		||||
  class QTKAPI Mesh {};
 | 
			
		||||
 | 
			
		||||
  /* Simple Cube shape. */
 | 
			
		||||
  struct QTKAPI Cube : public ShapeBase {
 | 
			
		||||
      explicit Cube(DrawMode mode = QTK_DRAW_ARRAYS);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  /* Simple Triangle shape. */
 | 
			
		||||
  struct QTKAPI Triangle : public ShapeBase {
 | 
			
		||||
      explicit Triangle(DrawMode mode = QTK_DRAW_ARRAYS);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
@ -8,8 +8,8 @@
 | 
			
		||||
 | 
			
		||||
#include <QImageReader>
 | 
			
		||||
 | 
			
		||||
#include <abstractscene.h>
 | 
			
		||||
#include <meshrenderer.h>
 | 
			
		||||
#include <scene.h>
 | 
			
		||||
#include <texture.h>
 | 
			
		||||
 | 
			
		||||
using namespace Qtk;
 | 
			
		||||
@ -31,6 +31,13 @@ MeshRenderer::~MeshRenderer() {
 | 
			
		||||
 | 
			
		||||
// Static member function to retrieve instances of MeshRenderers
 | 
			
		||||
MeshRenderer * MeshRenderer::getInstance(const QString & name) {
 | 
			
		||||
  if(!sInstances.contains(name)) {
 | 
			
		||||
#if QTK_DEBUG
 | 
			
		||||
    qDebug() << "Attempt to access MeshRenderer instance that does not exist! ("
 | 
			
		||||
             << qPrintable(name) << ")\n";
 | 
			
		||||
#endif
 | 
			
		||||
    return nullptr;
 | 
			
		||||
  }
 | 
			
		||||
  return sInstances[name];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -126,8 +133,8 @@ void MeshRenderer::setShaders(
 | 
			
		||||
void MeshRenderer::setUniformMVP(
 | 
			
		||||
    const char * model, const char * view, const char * projection) {
 | 
			
		||||
  ShaderBindScope lock(&mProgram, mBound);
 | 
			
		||||
  mProgram.setUniformValue(projection, Scene::Projection());
 | 
			
		||||
  mProgram.setUniformValue(view, Scene::View());
 | 
			
		||||
  mProgram.setUniformValue(projection, Scene::getProjectionMatrix());
 | 
			
		||||
  mProgram.setUniformValue(view, Scene::getViewMatrix());
 | 
			
		||||
  mProgram.setUniformValue(model, mTransform.toMatrix());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -141,6 +148,8 @@ void MeshRenderer::setColor(const QVector3D & color) {
 | 
			
		||||
      mShape.mColors[i] = color;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  // TODO: Factor this out so we don't need to reinitialize
 | 
			
		||||
  init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MeshRenderer::reallocateTexCoords(const TexCoords & t, unsigned dims) {
 | 
			
		||||
 | 
			
		||||
@ -15,31 +15,19 @@
 | 
			
		||||
#include <utility>
 | 
			
		||||
 | 
			
		||||
namespace Qtk {
 | 
			
		||||
  class QTKAPI ShaderBindScope {
 | 
			
		||||
    public:
 | 
			
		||||
      explicit ShaderBindScope(
 | 
			
		||||
          QOpenGLShaderProgram * program, bool was_locked) :
 | 
			
		||||
          mWasBound(was_locked) {
 | 
			
		||||
        mProgram = program;
 | 
			
		||||
        if(!mWasBound) {
 | 
			
		||||
          mProgram->bind();
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      ~ShaderBindScope() {
 | 
			
		||||
        if(!mWasBound) {
 | 
			
		||||
          mProgram->release();
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
      QOpenGLShaderProgram * mProgram;
 | 
			
		||||
      bool mWasBound;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  class QTKAPI MeshRenderer : public Object {
 | 
			
		||||
    public:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Typedefs
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      /* Static QHash of all mesh objects within the scene. */
 | 
			
		||||
      typedef QHash<QString, MeshRenderer *> MeshManager;
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Constructors / Destructors
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      // Delegate constructors
 | 
			
		||||
      MeshRenderer(
 | 
			
		||||
          const char * name, Vertices vertices, Indices indices,
 | 
			
		||||
@ -54,12 +42,28 @@ namespace Qtk {
 | 
			
		||||
      MeshRenderer(const char * name, const ShapeBase & shape);
 | 
			
		||||
      ~MeshRenderer() override;
 | 
			
		||||
 | 
			
		||||
      // Retrieve a mesh by name stored within a static QHash
 | 
			
		||||
      static MeshRenderer * getInstance(const QString & name);
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Public Methods
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      void init();
 | 
			
		||||
      void draw();
 | 
			
		||||
 | 
			
		||||
      inline void enableAttributeArray(int location) {
 | 
			
		||||
        ShaderBindScope lock(&mProgram, mBound);
 | 
			
		||||
        mVAO.bind();
 | 
			
		||||
        mProgram.enableAttributeArray(location);
 | 
			
		||||
        mVAO.release();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      void reallocateTexCoords(const TexCoords & t, unsigned dims = 2);
 | 
			
		||||
 | 
			
		||||
      void reallocateNormals(const Normals & n, unsigned dims = 3);
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Setters
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      // Draw types like GL_TRIANGLES, GL_POINTS, GL_LINES, etc
 | 
			
		||||
      void setDrawType(int drawType) { mDrawType = drawType; }
 | 
			
		||||
 | 
			
		||||
@ -105,21 +109,22 @@ namespace Qtk {
 | 
			
		||||
        mVAO.release();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      inline void enableAttributeArray(int location) {
 | 
			
		||||
        ShaderBindScope lock(&mProgram, mBound);
 | 
			
		||||
        mVAO.bind();
 | 
			
		||||
        mProgram.enableAttributeArray(location);
 | 
			
		||||
        mVAO.release();
 | 
			
		||||
      }
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Getters
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      void reallocateTexCoords(const TexCoords & t, unsigned dims = 2);
 | 
			
		||||
 | 
			
		||||
      void reallocateNormals(const Normals & n, unsigned dims = 3);
 | 
			
		||||
 | 
			
		||||
      // Static QHash of all mesh objects within the scene
 | 
			
		||||
      typedef QHash<QString, MeshRenderer *> MeshManager;
 | 
			
		||||
      /**
 | 
			
		||||
       * Retrieve a mesh by name stored within static QHash private member
 | 
			
		||||
       * @param name The name of the MeshRenderer we want to retrieve.
 | 
			
		||||
       * @return Pointer to the MeshRenderer, or nullptr if not found.
 | 
			
		||||
       */
 | 
			
		||||
      static MeshRenderer * getInstance(const QString & name);
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Private Members
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      static MeshManager sInstances;
 | 
			
		||||
 | 
			
		||||
      int mDrawType {};
 | 
			
		||||
 | 
			
		||||
@ -9,9 +9,9 @@
 | 
			
		||||
 | 
			
		||||
#include <QFileInfo>
 | 
			
		||||
 | 
			
		||||
#include <abstractscene.h>
 | 
			
		||||
#include <model.h>
 | 
			
		||||
#include <resourcemanager.h>
 | 
			
		||||
#include <scene.h>
 | 
			
		||||
#include <texture.h>
 | 
			
		||||
 | 
			
		||||
using namespace Qtk;
 | 
			
		||||
@ -97,8 +97,8 @@ void ModelMesh::draw(QOpenGLShaderProgram & shader) {
 | 
			
		||||
 | 
			
		||||
  // Set Model View Projection values
 | 
			
		||||
  shader.setUniformValue("uModel", mTransform.toMatrix());
 | 
			
		||||
  shader.setUniformValue("uView", Scene::View());
 | 
			
		||||
  shader.setUniformValue("uProjection", Scene::Projection());
 | 
			
		||||
  shader.setUniformValue("uView", Scene::getViewMatrix());
 | 
			
		||||
  shader.setUniformValue("uProjection", Scene::getProjectionMatrix());
 | 
			
		||||
 | 
			
		||||
  GLuint diffuseCount = 1;
 | 
			
		||||
  GLuint specularCount = 1;
 | 
			
		||||
@ -180,21 +180,6 @@ void Model::flipTexture(const std::string & fileName, bool flipX, bool flipY) {
 | 
			
		||||
 * Model Private Member Functions
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Loads a model in .obj, .fbx, .gltf, and other formats
 | 
			
		||||
 * For a full list of formats see assimp documentation:
 | 
			
		||||
 *  https://github.com/assimp/assimp/blob/master/doc/Fileformats.md
 | 
			
		||||
 *
 | 
			
		||||
 * Models should not be loaded into Qt resource system
 | 
			
		||||
 * Instead pass an *absolute* path to this function
 | 
			
		||||
 * Relative paths will break if Qtk is executed from different locations
 | 
			
		||||
 *
 | 
			
		||||
 * Models can also be loaded from the `qtk/resource` directory using qrc format
 | 
			
		||||
 *  loadModel(":/models/backpack/backpack.obj")
 | 
			
		||||
 * See resourcemanager.h for more information
 | 
			
		||||
 *
 | 
			
		||||
 * @param path Absolute path to a model .obj or other format accepted by assimp
 | 
			
		||||
 */
 | 
			
		||||
void Model::loadModel(const std::string & path) {
 | 
			
		||||
  Assimp::Importer import;
 | 
			
		||||
 | 
			
		||||
@ -362,7 +347,7 @@ ModelMesh::Textures Model::loadMaterialTextures(
 | 
			
		||||
    // If the texture has not yet been loaded
 | 
			
		||||
    if(!skip) {
 | 
			
		||||
      ModelTexture texture;
 | 
			
		||||
      texture.mTexture = OpenGLTextureFactory::initTexture2D(
 | 
			
		||||
      texture.mTexture = OpenGLTextureFactory::initTexture(
 | 
			
		||||
          std::string(mDirectory + '/' + fileName.C_Str()).c_str(), false,
 | 
			
		||||
          false);
 | 
			
		||||
      texture.mID = texture.mTexture->textureId();
 | 
			
		||||
@ -380,7 +365,7 @@ ModelMesh::Textures Model::loadMaterialTextures(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Model::sortModels() {
 | 
			
		||||
  auto cameraPos = Scene::Camera().transform();
 | 
			
		||||
  auto cameraPos = Scene::getCamera().getTransform();
 | 
			
		||||
  auto cameraDistance = [&cameraPos](const ModelMesh & a, const ModelMesh & b) {
 | 
			
		||||
    // Sort by the first vertex position in the model
 | 
			
		||||
    return (cameraPos.getTranslation().distanceToPoint(
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										157
									
								
								src/model.h
									
									
									
									
									
								
							
							
						
						
									
										157
									
								
								src/model.h
									
									
									
									
									
								
							@ -28,14 +28,20 @@
 | 
			
		||||
#include <transform3D.h>
 | 
			
		||||
 | 
			
		||||
namespace Qtk {
 | 
			
		||||
  /**
 | 
			
		||||
   * 3D models will store this data for each vertex in geometry
 | 
			
		||||
   */
 | 
			
		||||
  struct QTKAPI ModelVertex {
 | 
			
		||||
      QVector3D mPosition;
 | 
			
		||||
      QVector3D mNormal;
 | 
			
		||||
      QVector2D mTextureCoord;
 | 
			
		||||
      QVector3D mTangent;
 | 
			
		||||
      QVector3D mBitangent;
 | 
			
		||||
      QVector2D mTextureCoord;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Struct to store model textures. 3D Models may have multiple.
 | 
			
		||||
   */
 | 
			
		||||
  struct QTKAPI ModelTexture {
 | 
			
		||||
      GLuint mID {};
 | 
			
		||||
      QOpenGLTexture * mTexture {};
 | 
			
		||||
@ -45,14 +51,25 @@ namespace Qtk {
 | 
			
		||||
 | 
			
		||||
  class Model;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Mesh class specialized for storing 3D model data.
 | 
			
		||||
   * Eventually this can be consolidated into a more generic class.
 | 
			
		||||
   */
 | 
			
		||||
  class QTKAPI ModelMesh : protected QOpenGLFunctions {
 | 
			
		||||
    public:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Typedefs
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      friend Model;
 | 
			
		||||
      typedef std::vector<ModelVertex> Vertices;
 | 
			
		||||
      typedef std::vector<GLuint> Indices;
 | 
			
		||||
      typedef std::vector<ModelTexture> Textures;
 | 
			
		||||
 | 
			
		||||
      // Constructors, Destructors
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Constructors, Destructors
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      ModelMesh(
 | 
			
		||||
          Vertices vertices, Indices indices, Textures textures,
 | 
			
		||||
          const char * vertexShader = ":/model-basic.vert",
 | 
			
		||||
@ -68,78 +85,180 @@ namespace Qtk {
 | 
			
		||||
 | 
			
		||||
      ~ModelMesh() = default;
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
      void initMesh(const char * vert, const char * frag);
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Public Methods
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      // ModelMesh Private Members
 | 
			
		||||
      QOpenGLBuffer *mVBO, *mEBO;
 | 
			
		||||
      QOpenGLVertexArrayObject * mVAO;
 | 
			
		||||
      QOpenGLShaderProgram * mProgram;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
      inline void draw() { draw(*mProgram); }
 | 
			
		||||
 | 
			
		||||
      void draw(QOpenGLShaderProgram & shader);
 | 
			
		||||
 | 
			
		||||
      // ModelMesh Public Members
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Public Members
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      Vertices mVertices {};
 | 
			
		||||
      Indices mIndices {};
 | 
			
		||||
      Textures mTextures {};
 | 
			
		||||
      Transform3D mTransform;
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Private Methods
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      void initMesh(const char * vert, const char * frag);
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Private Members
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      QOpenGLBuffer *mVBO, *mEBO;
 | 
			
		||||
      QOpenGLVertexArrayObject * mVAO;
 | 
			
		||||
      QOpenGLShaderProgram * mProgram;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Model object that has a ModelMesh.
 | 
			
		||||
   * Top-level object that represents 3D models stored within a scene.
 | 
			
		||||
   */
 | 
			
		||||
  class QTKAPI Model : public QObject {
 | 
			
		||||
      Q_OBJECT
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Typedefs
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      /* ModelManager typedef that will manage global model access. */
 | 
			
		||||
      typedef QHash<QString, Model *> ModelManager;
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Constructors, Destructors
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      // Default model shaders are provided but we can override them in the ctor
 | 
			
		||||
      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) {
 | 
			
		||||
          mModelPath(path), mVertexShader(vertexShader),
 | 
			
		||||
          mFragmentShader(fragmentShader) {
 | 
			
		||||
        loadModel(path);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      inline ~Model() override { mManager.remove(mName); }
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Public Methods
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      void draw();
 | 
			
		||||
      void draw(QOpenGLShaderProgram & shader);
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Flip a texture associated with this model
 | 
			
		||||
       *
 | 
			
		||||
       * @param fileName The name of the texture to flip as it is stored on disk
 | 
			
		||||
       * @param flipX Flip the texture along the X axis
 | 
			
		||||
       * @param flipY Flip the texture along the Y axis
 | 
			
		||||
       */
 | 
			
		||||
      void flipTexture(
 | 
			
		||||
          const std::string & fileName, bool flipX = false, bool flipY = true);
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Setters
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Sets a uniform value
 | 
			
		||||
       *
 | 
			
		||||
       * @tparam T The type of the value we are settings
 | 
			
		||||
       * @param location The uniform location
 | 
			
		||||
       * @param value The value to assign to the uniform
 | 
			
		||||
       */
 | 
			
		||||
      template <typename T> void setUniform(const char * location, T value) {
 | 
			
		||||
        for(auto & mesh : mMeshes) {
 | 
			
		||||
          mesh.mProgram->bind();
 | 
			
		||||
 | 
			
		||||
          mesh.mProgram->setUniformValue(location, value);
 | 
			
		||||
 | 
			
		||||
          mesh.mProgram->release();
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      Transform3D mTransform;
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Accessors
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Accessor function for retrieving a ModelMesh globally.
 | 
			
		||||
       * The mesh is retrieved from the mManager private member.
 | 
			
		||||
       *
 | 
			
		||||
       * @param name The name of the model to load as it was constructed.
 | 
			
		||||
       * @return Pointer to the model stored within the scene.
 | 
			
		||||
       */
 | 
			
		||||
      static Model * getInstance(const char * name);
 | 
			
		||||
 | 
			
		||||
      typedef QHash<QString, Model *> ModelManager;
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Public Members
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      /* The position of this model in 3D space */
 | 
			
		||||
      // TODO: Make private
 | 
			
		||||
      Transform3D mTransform;
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
      static ModelManager mManager;
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Private Methods
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Loads a model in .obj, .fbx, .gltf, and other formats.
 | 
			
		||||
       * For a full list of formats see assimp documentation:
 | 
			
		||||
       *  https://github.com/assimp/assimp/blob/master/doc/Fileformats.md
 | 
			
		||||
       *
 | 
			
		||||
       * Models should not be loaded into Qt resource system.
 | 
			
		||||
       * Instead pass an *absolute* path to this function.
 | 
			
		||||
       * Relative paths will break if Qtk is executed from different locations.
 | 
			
		||||
       *
 | 
			
		||||
       * Models can also be loaded from the `qtk/resource` directory using qrc
 | 
			
		||||
       * format loadModel(":/models/backpack/backpack.obj").
 | 
			
		||||
       * This does not use Qt resource system, it just provides similar syntax
 | 
			
		||||
       * for accessing files within the same `resources/` directory.
 | 
			
		||||
       *
 | 
			
		||||
       * See resourcemanager.h for more information on how this works.
 | 
			
		||||
       *
 | 
			
		||||
       * @param path Absolute path to a model in .obj or another format accepted
 | 
			
		||||
       * by assimp.
 | 
			
		||||
       */
 | 
			
		||||
      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
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Private Members
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      /* Static QHash used to store and access models globally. */
 | 
			
		||||
      static ModelManager mManager;
 | 
			
		||||
 | 
			
		||||
      /* Container to store N loaded textures for this model. */
 | 
			
		||||
      ModelMesh::Textures mTexturesLoaded {};
 | 
			
		||||
      /* Container to store N loaded meshes for this model. */
 | 
			
		||||
      std::vector<ModelMesh> mMeshes {};
 | 
			
		||||
      /* The directory this model and it's textures are stored. */
 | 
			
		||||
      std::string mDirectory {};
 | 
			
		||||
      const char *mVertexShader, *mFragmentShader, *mName;
 | 
			
		||||
      /* File names for shaders and 3D model on disk. */
 | 
			
		||||
      const char *mVertexShader, *mFragmentShader, *mModelPath;
 | 
			
		||||
      /* Name of the model object within the scene. */
 | 
			
		||||
      const char * mName;
 | 
			
		||||
  };
 | 
			
		||||
}  // namespace Qtk
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										34
									
								
								src/object.h
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								src/object.h
									
									
									
									
									
								
							@ -18,12 +18,24 @@
 | 
			
		||||
#include <texture.h>
 | 
			
		||||
 | 
			
		||||
namespace Qtk {
 | 
			
		||||
  /**
 | 
			
		||||
   * Object base class for objects that can exist within a scene.
 | 
			
		||||
   * An object could be a Cube, Skybox, 3D Model, or other standalone entities.
 | 
			
		||||
   */
 | 
			
		||||
  class QTKAPI Object : public QObject {
 | 
			
		||||
      Q_OBJECT
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Typedefs
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      friend MeshRenderer;
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Constructors / Destructors
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      // Initialize an object with no shape data assigned
 | 
			
		||||
      explicit Object(const char * name) :
 | 
			
		||||
          mName(name), mVBO(QOpenGLBuffer::VertexBuffer), mBound(false) {}
 | 
			
		||||
@ -35,6 +47,10 @@ namespace Qtk {
 | 
			
		||||
 | 
			
		||||
      ~Object() override = default;
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Accessors
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      inline const Colors & getColors() { return mShape.mColors; }
 | 
			
		||||
 | 
			
		||||
      inline const Indices & getIndexData() { return mShape.mIndices; }
 | 
			
		||||
@ -49,6 +65,10 @@ namespace Qtk {
 | 
			
		||||
 | 
			
		||||
      inline const Vertices & getVertices() { return mShape.mVertices; }
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Setters
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      virtual inline void setColors(const Colors & value) {
 | 
			
		||||
        mShape.mColors = value;
 | 
			
		||||
      }
 | 
			
		||||
@ -84,6 +104,10 @@ namespace Qtk {
 | 
			
		||||
        mShape.mVertices = value;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Public Methods
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      virtual inline void bindShaders() {
 | 
			
		||||
        mBound = true;
 | 
			
		||||
        mProgram.bind();
 | 
			
		||||
@ -94,6 +118,10 @@ namespace Qtk {
 | 
			
		||||
        mProgram.release();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Public Members
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      QOpenGLBuffer mVBO, mNBO;
 | 
			
		||||
      QOpenGLVertexArrayObject mVAO;
 | 
			
		||||
 | 
			
		||||
@ -104,9 +132,9 @@ namespace Qtk {
 | 
			
		||||
      bool mBound;
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
      virtual inline void setTexture(QOpenGLTexture * value) {
 | 
			
		||||
        mTexture.setTexture(value);
 | 
			
		||||
      }
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Private Members
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      QOpenGLShaderProgram mProgram;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
@ -8,10 +8,10 @@
 | 
			
		||||
 | 
			
		||||
#include <QKeyEvent>
 | 
			
		||||
 | 
			
		||||
#include <abstractscene.h>
 | 
			
		||||
#include <input.h>
 | 
			
		||||
#include <mesh.h>
 | 
			
		||||
#include <qtkwidget.h>
 | 
			
		||||
#include <scene.h>
 | 
			
		||||
 | 
			
		||||
using namespace Qtk;
 | 
			
		||||
 | 
			
		||||
@ -23,7 +23,6 @@ QtkWidget::QtkWidget() : mScene(Q_NULLPTR), mDebugLogger(Q_NULLPTR) {
 | 
			
		||||
  initializeWidget();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Constructor for using this widget in QtDesigner
 | 
			
		||||
QtkWidget::QtkWidget(QWidget * parent) :
 | 
			
		||||
    QOpenGLWidget(parent), mScene(Q_NULLPTR), mDebugLogger(Q_NULLPTR) {
 | 
			
		||||
  initializeWidget();
 | 
			
		||||
@ -41,27 +40,9 @@ QtkWidget::~QtkWidget() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * Private Member Functions
 | 
			
		||||
 * Public Inherited Virtual Methods
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
void QtkWidget::teardownGL() {
 | 
			
		||||
  // Nothing to teardown yet...
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * Inherited Virtual Member Functions
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
void QtkWidget::paintGL() {
 | 
			
		||||
  // Clear buffers
 | 
			
		||||
  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
 | 
			
		||||
 | 
			
		||||
  // Draw the scene first, since it handles drawing our skybox
 | 
			
		||||
  if(mScene != Q_NULLPTR) {
 | 
			
		||||
    mScene->draw();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QtkWidget::initializeGL() {
 | 
			
		||||
  initializeOpenGLFunctions();
 | 
			
		||||
  // Connect the frameSwapped signal to call the update() function
 | 
			
		||||
@ -93,11 +74,19 @@ void QtkWidget::initializeGL() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QtkWidget::resizeGL(int width, int height) {
 | 
			
		||||
  Scene::Projection().setToIdentity();
 | 
			
		||||
  Scene::Projection().perspective(
 | 
			
		||||
  Scene::getProjectionMatrix().setToIdentity();
 | 
			
		||||
  Scene::getProjectionMatrix().perspective(
 | 
			
		||||
      45.0f, float(width) / float(height), 0.1f, 1000.0f);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QtkWidget::paintGL() {
 | 
			
		||||
  // Clear buffers and draw the scene if it is valid.
 | 
			
		||||
  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
 | 
			
		||||
  if(mScene != Q_NULLPTR) {
 | 
			
		||||
    mScene->draw();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * Protected Slots
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
@ -175,7 +164,7 @@ void QtkWidget::messageLogged(const QOpenGLDebugMessage & msg) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * Protected Helpers
 | 
			
		||||
 * Protected Methods
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
void QtkWidget::keyPressEvent(QKeyEvent * event) {
 | 
			
		||||
@ -204,7 +193,7 @@ void QtkWidget::mouseReleaseEvent(QMouseEvent * event) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * Private Helpers
 | 
			
		||||
 * Private Methods
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
void QtkWidget::initializeWidget() {
 | 
			
		||||
@ -265,31 +254,31 @@ void QtkWidget::updateCameraInput() {
 | 
			
		||||
    static const float rotSpeed = 0.5f;
 | 
			
		||||
 | 
			
		||||
    // Handle rotations
 | 
			
		||||
    Scene::Camera().transform().rotate(
 | 
			
		||||
    Scene::getCamera().getTransform().rotate(
 | 
			
		||||
        -rotSpeed * Input::mouseDelta().x(), Camera3D::LocalUp);
 | 
			
		||||
    Scene::Camera().transform().rotate(
 | 
			
		||||
        -rotSpeed * Input::mouseDelta().y(), Scene::Camera().right());
 | 
			
		||||
    Scene::getCamera().getTransform().rotate(
 | 
			
		||||
        -rotSpeed * Input::mouseDelta().y(), Scene::getCamera().right());
 | 
			
		||||
 | 
			
		||||
    // Handle translations
 | 
			
		||||
    QVector3D translation;
 | 
			
		||||
    if(Input::keyPressed(Qt::Key_W)) {
 | 
			
		||||
      translation += Scene::Camera().forward();
 | 
			
		||||
      translation += Scene::getCamera().forward();
 | 
			
		||||
    }
 | 
			
		||||
    if(Input::keyPressed(Qt::Key_S)) {
 | 
			
		||||
      translation -= Scene::Camera().forward();
 | 
			
		||||
      translation -= Scene::getCamera().forward();
 | 
			
		||||
    }
 | 
			
		||||
    if(Input::keyPressed(Qt::Key_A)) {
 | 
			
		||||
      translation -= Scene::Camera().right();
 | 
			
		||||
      translation -= Scene::getCamera().right();
 | 
			
		||||
    }
 | 
			
		||||
    if(Input::keyPressed(Qt::Key_D)) {
 | 
			
		||||
      translation += Scene::Camera().right();
 | 
			
		||||
      translation += Scene::getCamera().right();
 | 
			
		||||
    }
 | 
			
		||||
    if(Input::keyPressed(Qt::Key_Q)) {
 | 
			
		||||
      translation -= Scene::Camera().up() / 2.0f;
 | 
			
		||||
      translation -= Scene::getCamera().up() / 2.0f;
 | 
			
		||||
    }
 | 
			
		||||
    if(Input::keyPressed(Qt::Key_E)) {
 | 
			
		||||
      translation += Scene::Camera().up() / 2.0f;
 | 
			
		||||
      translation += Scene::getCamera().up() / 2.0f;
 | 
			
		||||
    }
 | 
			
		||||
    Scene::Camera().transform().translate(transSpeed * translation);
 | 
			
		||||
    Scene::getCamera().getTransform().translate(transSpeed * translation);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -15,60 +15,141 @@
 | 
			
		||||
#include <QOpenGLFunctions>
 | 
			
		||||
#include <QOpenGLWidget>
 | 
			
		||||
 | 
			
		||||
#include <abstractscene.h>
 | 
			
		||||
#include <qtkapi.h>
 | 
			
		||||
#include <scene.h>
 | 
			
		||||
 | 
			
		||||
namespace Qtk {
 | 
			
		||||
  /**
 | 
			
		||||
   * QtkWidget class to define required QOpenGLWidget functionality.
 | 
			
		||||
   *
 | 
			
		||||
   * This object has a Scene attached which manages the objects to render.
 | 
			
		||||
   * Client input is passed through this widget to control the camera view.
 | 
			
		||||
   */
 | 
			
		||||
  class QTKAPI QtkWidget : public QOpenGLWidget, protected QOpenGLFunctions {
 | 
			
		||||
      Q_OBJECT;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
      // Constructors
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Contructors / Destructors
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Default ctor will configure a QSurfaceFormat with default settings.
 | 
			
		||||
       */
 | 
			
		||||
      QtkWidget();
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Qt Designer will call this ctor when creating this widget as a child.
 | 
			
		||||
       *
 | 
			
		||||
       * @param parent The parent QWidget
 | 
			
		||||
       */
 | 
			
		||||
      explicit QtkWidget(QWidget * parent);
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Allow constructing the widget with a preconfigured QSurfaceFormat.
 | 
			
		||||
       *
 | 
			
		||||
       * @param format QSurfaceFormat already configured by the caller.
 | 
			
		||||
       */
 | 
			
		||||
      explicit QtkWidget(const QSurfaceFormat & format);
 | 
			
		||||
 | 
			
		||||
      ~QtkWidget() override;
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
      void teardownGL();
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Private Methods
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      // clang-format off
 | 
			
		||||
      void teardownGL() { /* Nothing to teardown yet... */ }
 | 
			
		||||
      // clang-format on
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
      // Inherited virtual Members
 | 
			
		||||
      void paintGL() override;
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Public Inherited Virtual Methods
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Called when the widget is first constructed.
 | 
			
		||||
       */
 | 
			
		||||
      void initializeGL() override;
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Called when the application window is resized.
 | 
			
		||||
       *
 | 
			
		||||
       * @param width The new width of the window.
 | 
			
		||||
       * @param height The new height of the window.
 | 
			
		||||
       */
 | 
			
		||||
      void resizeGL(int width, int height) override;
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Called when OpenGL repaints the widget.
 | 
			
		||||
       */
 | 
			
		||||
      void paintGL() override;
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Accessors
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      inline Qtk::Scene * getScene() { return mScene; }
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Setters
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      inline void setScene(Qtk::Scene * scene) {
 | 
			
		||||
        delete mScene;
 | 
			
		||||
 | 
			
		||||
        mScene = scene;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    protected slots:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Qt Slots
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Called when the `frameSwapped` signal is caught.
 | 
			
		||||
       * See definition of initializeGL()
 | 
			
		||||
       */
 | 
			
		||||
      void update();
 | 
			
		||||
 | 
			
		||||
#ifdef QTK_DEBUG
 | 
			
		||||
      /**
 | 
			
		||||
       * Called when the `messageLogged` signal is caught.
 | 
			
		||||
       * See definition of initializeGL()
 | 
			
		||||
       *
 | 
			
		||||
       * @param msg The message logged.
 | 
			
		||||
       */
 | 
			
		||||
      static void messageLogged(const QOpenGLDebugMessage & msg);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
      // Protected Helpers
 | 
			
		||||
    protected:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Protected Methods
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      void keyPressEvent(QKeyEvent * event) override;
 | 
			
		||||
      void keyReleaseEvent(QKeyEvent * event) override;
 | 
			
		||||
      void mousePressEvent(QMouseEvent * event) override;
 | 
			
		||||
      void mouseReleaseEvent(QMouseEvent * event) override;
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
      // Private helpers
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Private Methods
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      void initializeWidget();
 | 
			
		||||
      static void updateCameraInput();
 | 
			
		||||
 | 
			
		||||
      Qtk::Scene * mScene;
 | 
			
		||||
#ifdef QTK_DEBUG
 | 
			
		||||
      void printContextInformation();
 | 
			
		||||
      QOpenGLDebugLogger * mDebugLogger;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Private Members
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      Qtk::Scene * mScene;
 | 
			
		||||
  };
 | 
			
		||||
}  // namespace Qtk
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -6,9 +6,9 @@
 | 
			
		||||
## Contact: shaunrd0@gmail.com  | URL: www.shaunreed.com | GitHub: shaunrd0   ##
 | 
			
		||||
##############################################################################*/
 | 
			
		||||
 | 
			
		||||
#include <abstractscene.h>
 | 
			
		||||
#include <camera3d.h>
 | 
			
		||||
#include <resourcemanager.h>
 | 
			
		||||
#include <scene.h>
 | 
			
		||||
#include <texture.h>
 | 
			
		||||
 | 
			
		||||
using namespace Qtk;
 | 
			
		||||
@ -21,8 +21,8 @@ QMatrix4x4 Scene::mProjection;
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
Scene::Scene() {
 | 
			
		||||
  mCamera.transform().setTranslation(0.0f, 0.0f, 20.0f);
 | 
			
		||||
  mCamera.transform().setRotation(-5.0f, 0.0f, 1.0f, 0.0f);
 | 
			
		||||
  mCamera.getTransform().setTranslation(0.0f, 0.0f, 20.0f);
 | 
			
		||||
  mCamera.getTransform().setRotation(-5.0f, 0.0f, 1.0f, 0.0f);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Scene::~Scene() {
 | 
			
		||||
@ -32,11 +32,10 @@ Scene::~Scene() {
 | 
			
		||||
  for(auto & model : mModels) {
 | 
			
		||||
    delete model;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  delete mSkybox;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Scene::privDraw() {
 | 
			
		||||
void Scene::privateDraw() {
 | 
			
		||||
  if(!mInit) {
 | 
			
		||||
    initializeOpenGLFunctions();
 | 
			
		||||
    init();
 | 
			
		||||
							
								
								
									
										125
									
								
								src/scene.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								src/scene.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,125 @@
 | 
			
		||||
/*##############################################################################
 | 
			
		||||
## 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 {
 | 
			
		||||
  /**
 | 
			
		||||
   * An abstract Scene class to inherit from when building new scenes.
 | 
			
		||||
   *
 | 
			
		||||
   * This class provides the following objects to any inheriting scene:
 | 
			
		||||
   *    Skybox, Camera
 | 
			
		||||
   * This class also provides containers for N instances of these objects:
 | 
			
		||||
   *    MeshRenderers, Models
 | 
			
		||||
   *
 | 
			
		||||
   * To inherit from this class and define our own scene we must:
 | 
			
		||||
   *
 | 
			
		||||
   * Override and define the `init()` virtual member function. If we want our
 | 
			
		||||
   * scene to render using a Skybox, we should also initialize the mSkybox
 | 
			
		||||
   * member within the overridden definition of `init()` using
 | 
			
		||||
   * `Scene::setSkybox(...)`
 | 
			
		||||
   *
 | 
			
		||||
   * If the scene is to render any kind of movement we are required to override
 | 
			
		||||
   * the `update()` virtual method.
 | 
			
		||||
   *
 | 
			
		||||
   * If the child scene adds any objects which are not managed (drawn) by this
 | 
			
		||||
   * base class, the child scene class must also override the `draw()` method.
 | 
			
		||||
   */
 | 
			
		||||
  class Scene : protected QOpenGLFunctions {
 | 
			
		||||
    public:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Contructors / Destructors
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      Scene();
 | 
			
		||||
 | 
			
		||||
      ~Scene();
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Public Methods
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Initialize objects within the scene
 | 
			
		||||
       */
 | 
			
		||||
      virtual void init() = 0;
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Function called during OpenGL drawing event.
 | 
			
		||||
       *
 | 
			
		||||
       * This function is only called when the widget is redrawn.
 | 
			
		||||
       */
 | 
			
		||||
      virtual void draw() { privateDraw(); };
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Function called to update the QOpenGLWidget. Does not trigger a redraw.
 | 
			
		||||
       *
 | 
			
		||||
       * Calling this several times will still result in only one repaint.
 | 
			
		||||
       */
 | 
			
		||||
      virtual void update() {}
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Accessors
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      static Camera3D & getCamera() { return mCamera; }
 | 
			
		||||
 | 
			
		||||
      static QMatrix4x4 getViewMatrix() { return mCamera.toMatrix(); }
 | 
			
		||||
 | 
			
		||||
      static QMatrix4x4 & getProjectionMatrix() { return mProjection; }
 | 
			
		||||
 | 
			
		||||
      inline Skybox * getSkybox() { return mSkybox; }
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Setters
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      inline void setSkybox(Skybox * skybox) { mSkybox = skybox; }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Private Members
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      static Camera3D mCamera;
 | 
			
		||||
      static QMatrix4x4 mProjection;
 | 
			
		||||
      bool mInit = false;
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Private Methods
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Handles drawing members encapsulated by this base class.
 | 
			
		||||
       * Child classes do not need to draw these objects manually.
 | 
			
		||||
       */
 | 
			
		||||
      void privateDraw();
 | 
			
		||||
 | 
			
		||||
    protected:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Protected Members
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      /* The skybox for this scene. */
 | 
			
		||||
      Skybox * mSkybox {};
 | 
			
		||||
      /* MeshRenderers used simple geometry. */
 | 
			
		||||
      std::vector<MeshRenderer *> mMeshes {};
 | 
			
		||||
      /* Models used for storing 3D models in the scene. */
 | 
			
		||||
      std::vector<Model *> mModels {};
 | 
			
		||||
  };
 | 
			
		||||
}  // namespace Qtk
 | 
			
		||||
 | 
			
		||||
#endif  // QTK_SCENE_H
 | 
			
		||||
@ -6,7 +6,7 @@
 | 
			
		||||
## Contact: shaunrd0@gmail.com  | URL: www.shaunreed.com | GitHub: shaunrd0   ##
 | 
			
		||||
##############################################################################*/
 | 
			
		||||
 | 
			
		||||
#include <abstractscene.h>
 | 
			
		||||
#include <scene.h>
 | 
			
		||||
#include <skybox.h>
 | 
			
		||||
#include <texture.h>
 | 
			
		||||
 | 
			
		||||
@ -32,8 +32,8 @@ Skybox::Skybox(const std::string & name) :
 | 
			
		||||
        ":/right.png", ":/top.png", ":/front.png", ":/left.png", ":/bottom.png",
 | 
			
		||||
        ":/back.png", name) {}
 | 
			
		||||
 | 
			
		||||
Skybox::Skybox(QOpenGLTexture * cubeMap, const std::string & name) :
 | 
			
		||||
    mTexture(cubeMap) {
 | 
			
		||||
Skybox::Skybox(QOpenGLTexture * cubeMap, const std::string & name) {
 | 
			
		||||
  mTexture.setTexture(cubeMap);
 | 
			
		||||
  init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -49,8 +49,8 @@ void Skybox::draw() {
 | 
			
		||||
  mProgram.bind();
 | 
			
		||||
  mTexture.getOpenGLTexture().bind();
 | 
			
		||||
 | 
			
		||||
  mProgram.setUniformValue("uProjectionMatrix", Scene::Projection());
 | 
			
		||||
  mProgram.setUniformValue("uViewMatrix", Scene::Camera().toMatrix());
 | 
			
		||||
  mProgram.setUniformValue("uProjectionMatrix", Scene::getProjectionMatrix());
 | 
			
		||||
  mProgram.setUniformValue("uViewMatrix", Scene::getCamera().toMatrix());
 | 
			
		||||
  mProgram.setUniformValue("uTexture", 0);
 | 
			
		||||
  glDrawElements(
 | 
			
		||||
      GL_TRIANGLES, mIndices.size(), GL_UNSIGNED_INT, mIndices.data());
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										24
									
								
								src/skybox.h
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								src/skybox.h
									
									
									
									
									
								
							@ -21,13 +21,23 @@
 | 
			
		||||
#include <texture.h>
 | 
			
		||||
 | 
			
		||||
namespace Qtk {
 | 
			
		||||
  /**
 | 
			
		||||
   * Skybox object for rendering a skybox within a Scene.
 | 
			
		||||
   * A skybox is typically implemented using a cube map texture centered around
 | 
			
		||||
   * the camera and projected outwards in all directions.
 | 
			
		||||
   */
 | 
			
		||||
  class QTKAPI Skybox : protected QOpenGLFunctions {
 | 
			
		||||
    public:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Constructors / Destructors
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      // Delegate this constructor to use default skybox images
 | 
			
		||||
      explicit Skybox(const std::string & name = "Skybox");
 | 
			
		||||
 | 
			
		||||
      explicit Skybox(
 | 
			
		||||
          QOpenGLTexture * cubeMap, const std::string & name = "Skybox");
 | 
			
		||||
      // Constructor, Destructor
 | 
			
		||||
 | 
			
		||||
      Skybox(
 | 
			
		||||
          const std::string & right, const std::string & top,
 | 
			
		||||
          const std::string & front, const std::string & left,
 | 
			
		||||
@ -36,11 +46,23 @@ namespace Qtk {
 | 
			
		||||
 | 
			
		||||
      ~Skybox() = default;
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Public Methods
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      void draw();
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Private Methods
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      void init();
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Private Members
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      Vertices mVertices {};
 | 
			
		||||
      Indices mIndices {};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -28,7 +28,7 @@ QImage * OpenGLTextureFactory::initImage(
 | 
			
		||||
  return loadedImage;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QOpenGLTexture * OpenGLTextureFactory::initTexture2D(
 | 
			
		||||
QOpenGLTexture * OpenGLTextureFactory::initTexture(
 | 
			
		||||
    const char * texture, bool flipX, bool flipY) {
 | 
			
		||||
  QImage * image = initImage(texture, flipX, flipY);
 | 
			
		||||
  auto newTexture = new QOpenGLTexture(QOpenGLTexture::Target2D);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										158
									
								
								src/texture.h
									
									
									
									
									
								
							
							
						
						
									
										158
									
								
								src/texture.h
									
									
									
									
									
								
							@ -9,30 +9,124 @@
 | 
			
		||||
#ifndef QTOPENGL_TEXTURE_H
 | 
			
		||||
#define QTOPENGL_TEXTURE_H
 | 
			
		||||
 | 
			
		||||
#include <QOpenGLShaderProgram>
 | 
			
		||||
#include <QOpenGLTexture>
 | 
			
		||||
#include <utility>
 | 
			
		||||
 | 
			
		||||
#include <qtkapi.h>
 | 
			
		||||
 | 
			
		||||
namespace Qtk {
 | 
			
		||||
  /**
 | 
			
		||||
   * Binds shader programs until the end of scope.
 | 
			
		||||
   * Does nothing if the shader program was already bound.
 | 
			
		||||
   *
 | 
			
		||||
   * See MeshRenderer::setUniform() for example.
 | 
			
		||||
   */
 | 
			
		||||
  class QTKAPI ShaderBindScope {
 | 
			
		||||
    public:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Constructors / Destructors
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      explicit ShaderBindScope(
 | 
			
		||||
          QOpenGLShaderProgram * program, bool was_locked) :
 | 
			
		||||
          mWasBound(was_locked) {
 | 
			
		||||
        mProgram = program;
 | 
			
		||||
        if(!mWasBound) {
 | 
			
		||||
          mProgram->bind();
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      ~ShaderBindScope() {
 | 
			
		||||
        if(!mWasBound) {
 | 
			
		||||
          mProgram->release();
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Private Members
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      QOpenGLShaderProgram * mProgram;
 | 
			
		||||
      bool mWasBound;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Factories for initializing various OpenGL textures
 | 
			
		||||
   */
 | 
			
		||||
  class QTKAPI OpenGLTextureFactory {
 | 
			
		||||
    public:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Constructors / Destructors
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
      ~OpenGLTextureFactory() = default;
 | 
			
		||||
 | 
			
		||||
      // QImage
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Texture Factories
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * QImage factory
 | 
			
		||||
       *
 | 
			
		||||
       * @param image Path to image we want to load.
 | 
			
		||||
       *    Can be absolute or Qt resource path.
 | 
			
		||||
       * @param flipX If true the image will be flipped on X axis.
 | 
			
		||||
       * @param flipY If true the image will be flipped on Y axis.
 | 
			
		||||
       * @return Pointer to an initialized QImage object.
 | 
			
		||||
       */
 | 
			
		||||
      static QImage * initImage(
 | 
			
		||||
          const char * image, bool flipX = false, bool flipY = false);
 | 
			
		||||
 | 
			
		||||
      // 2D Texture
 | 
			
		||||
      static QOpenGLTexture * initTexture2D(
 | 
			
		||||
      /**
 | 
			
		||||
       * QOpenGLTexture factory
 | 
			
		||||
       *
 | 
			
		||||
       * @param texture Path to texture we want to load.
 | 
			
		||||
       *    Can be absolute or Qt resource path.
 | 
			
		||||
       * @param flipX If true the image will be flipped on X axis.
 | 
			
		||||
       * @param flipY If true the image will be flipped on Y axis.
 | 
			
		||||
       * @return Pointer to an initialized QOpenGLTexture object.
 | 
			
		||||
       */
 | 
			
		||||
      static QOpenGLTexture * initTexture(
 | 
			
		||||
          const char * texture, bool flipX = false, bool flipY = false);
 | 
			
		||||
 | 
			
		||||
      // Cube maps
 | 
			
		||||
      /**
 | 
			
		||||
       * Cube map factory for initializing all sides of a CubeMap.
 | 
			
		||||
       * All of these parameters can be absolute or Qt resource paths.
 | 
			
		||||
       *
 | 
			
		||||
       * @param right Path to image for the right side of the CubeMap.
 | 
			
		||||
       * @param top Path to image for the top side of the CubeMap.
 | 
			
		||||
       * @param front Path to image for the front side of the CubeMap.
 | 
			
		||||
       * @param left Path to image for the left side of the CubeMap.
 | 
			
		||||
       * @param bottom Path to image for the bottom side of the CubeMap.
 | 
			
		||||
       * @param back Path to image for the back side of the CubeMap.
 | 
			
		||||
       * @return Pointer to an initialized QOpenGLTexture object.
 | 
			
		||||
       */
 | 
			
		||||
      static QOpenGLTexture * initCubeMap(
 | 
			
		||||
          const QImage & right, const QImage & top, const QImage & front,
 | 
			
		||||
          const QImage & left, const QImage & bottom, const QImage & back);
 | 
			
		||||
      // Overloads for cube map initialization
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * CubeMap factory for tiling the same image on all sides.
 | 
			
		||||
       *
 | 
			
		||||
       * @param tile Path to the image we want to make into a CubeMap.
 | 
			
		||||
       *    Can be absolute or Qt resource path.
 | 
			
		||||
       * @return Pointer to an initialized QOpenGLTexture object.
 | 
			
		||||
       */
 | 
			
		||||
      static QOpenGLTexture * initCubeMap(const char * tile);
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Cube map factory for initializing all sides of a CubeMap.
 | 
			
		||||
       * All of these parameters can be absolute or Qt resource paths.
 | 
			
		||||
       *
 | 
			
		||||
       * @param right Path to image for the right side of the CubeMap.
 | 
			
		||||
       * @param top Path to image for the top side of the CubeMap.
 | 
			
		||||
       * @param front Path to image for the front side of the CubeMap.
 | 
			
		||||
       * @param left Path to image for the left side of the CubeMap.
 | 
			
		||||
       * @param bottom Path to image for the bottom side of the CubeMap.
 | 
			
		||||
       * @param back Path to image for the back side of the CubeMap.
 | 
			
		||||
       * @return Pointer to an initialized QOpenGLTexture object.
 | 
			
		||||
       */
 | 
			
		||||
      static QOpenGLTexture * initCubeMap(
 | 
			
		||||
          const char * right, const char * top, const char * front,
 | 
			
		||||
          const char * left, const char * bottom, const char * back);
 | 
			
		||||
@ -42,48 +136,66 @@ namespace Qtk {
 | 
			
		||||
      OpenGLTextureFactory() = default;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // TODO: Struct for (re)storing texture state
 | 
			
		||||
  /**
 | 
			
		||||
   * Texture object component class
 | 
			
		||||
   *
 | 
			
		||||
   * TODO: Struct for (re)storing texture state
 | 
			
		||||
   * A struct to store flipX, flipY and other initial state needed to copy
 | 
			
		||||
   */
 | 
			
		||||
  class Texture {
 | 
			
		||||
    public:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Typedefs
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
      friend class Skybox;
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Constructors / Destructors
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      Texture() = default;
 | 
			
		||||
 | 
			
		||||
      Texture(const Texture & value) {
 | 
			
		||||
        mOpenGLTexture = OpenGLTextureFactory::initTexture2D(value.mPath);
 | 
			
		||||
        mOpenGLTexture = OpenGLTextureFactory::initTexture(value.mPath);
 | 
			
		||||
        mPath = value.mPath;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      explicit Texture(
 | 
			
		||||
          const char * path, bool flipX = false, bool flipY = false) :
 | 
			
		||||
          mOpenGLTexture(
 | 
			
		||||
              OpenGLTextureFactory::initTexture2D(path, flipX, flipY)),
 | 
			
		||||
          mOpenGLTexture(OpenGLTextureFactory::initTexture(path, flipX, flipY)),
 | 
			
		||||
          mPath(path) {}
 | 
			
		||||
 | 
			
		||||
      explicit Texture(QOpenGLTexture * texture) : mOpenGLTexture(texture) {}
 | 
			
		||||
 | 
			
		||||
      ~Texture() { mOpenGLTexture->destroy(); }
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Accessors
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      [[nodiscard]] inline QOpenGLTexture & getOpenGLTexture() const {
 | 
			
		||||
        return *mOpenGLTexture;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      [[nodiscard]] inline std::string getPath() const { return mPath; }
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Setters
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      void setTexture(
 | 
			
		||||
          const std::string & path, bool flipX = false, bool flipY = false) {
 | 
			
		||||
        mOpenGLTexture =
 | 
			
		||||
            OpenGLTextureFactory::initTexture2D(path.data(), flipX, flipY);
 | 
			
		||||
            OpenGLTextureFactory::initTexture(path.data(), flipX, flipY);
 | 
			
		||||
        mPath = path.data();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      void setTexture(
 | 
			
		||||
          const char * path, bool flipX = false, bool flipY = false) {
 | 
			
		||||
        mOpenGLTexture =
 | 
			
		||||
            OpenGLTextureFactory::initTexture2D(path, flipX, flipY);
 | 
			
		||||
        mOpenGLTexture = OpenGLTextureFactory::initTexture(path, flipX, flipY);
 | 
			
		||||
        mPath = path;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // TODO: This is unsafe because we don't have a path. Encapsulate it.
 | 
			
		||||
      inline void setTexture(QOpenGLTexture * texture) {
 | 
			
		||||
        mOpenGLTexture = texture;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      virtual inline void setCubeMap(const char * path) {
 | 
			
		||||
        mOpenGLTexture = OpenGLTextureFactory::initCubeMap(path);
 | 
			
		||||
        mPath = path;
 | 
			
		||||
@ -103,12 +215,24 @@ namespace Qtk {
 | 
			
		||||
            right, top, front, left, bottom, back);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Public Methods
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      [[nodiscard]] inline bool hasTexture() const {
 | 
			
		||||
        return mOpenGLTexture != Q_NULLPTR;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Private Members
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
      inline void setTexture(QOpenGLTexture * texture) {
 | 
			
		||||
        mOpenGLTexture = texture;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      QOpenGLTexture * mOpenGLTexture = Q_NULLPTR;
 | 
			
		||||
      /* Path to this texture on disk or Qt resource. */
 | 
			
		||||
      const char * mPath {};
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -23,15 +23,22 @@
 | 
			
		||||
#include <qtkapi.h>
 | 
			
		||||
 | 
			
		||||
namespace Qtk {
 | 
			
		||||
  /**
 | 
			
		||||
   * Transform3D class to represent and modify object position in 3D space.
 | 
			
		||||
   */
 | 
			
		||||
  class QTKAPI Transform3D {
 | 
			
		||||
    public:
 | 
			
		||||
      // Constructors
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Constructors, Destructors
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      inline Transform3D() :
 | 
			
		||||
          m_dirty(true), mScale(1.0f, 1.0f, 1.0f),
 | 
			
		||||
          mTranslation(0.0f, 0.0f, 0.0f) {}
 | 
			
		||||
 | 
			
		||||
      //
 | 
			
		||||
      // Transformations
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Transformations
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      void translate(const QVector3D & dt);
 | 
			
		||||
 | 
			
		||||
@ -72,8 +79,9 @@ namespace Qtk {
 | 
			
		||||
        grow(QVector3D(factor, factor, factor));
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      //
 | 
			
		||||
      // Setters
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Setters
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      // Set object position
 | 
			
		||||
      void setTranslation(const QVector3D & t);
 | 
			
		||||
@ -102,8 +110,9 @@ namespace Qtk {
 | 
			
		||||
        setRotation(QQuaternion::fromAxisAndAngle(ax, ay, az, angle));
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      //
 | 
			
		||||
      // Accessors
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Getters
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      [[nodiscard]] inline const QVector3D & getTranslation() const {
 | 
			
		||||
        return mTranslation;
 | 
			
		||||
@ -121,9 +130,17 @@ namespace Qtk {
 | 
			
		||||
      [[nodiscard]] QVector3D getUp() const;
 | 
			
		||||
      [[nodiscard]] QVector3D getRight() const;
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Public members
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      static const QVector3D LocalForward, LocalUp, LocalRight;
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Private members
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      QVector3D mTranslation;
 | 
			
		||||
      QQuaternion mRotation;
 | 
			
		||||
      QVector3D mScale;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user