Work on adding more doxygen comments #12
|
@ -1,8 +1,5 @@
|
||||||
|
|
||||||
---
|
---
|
||||||
# clang-format off
|
|
||||||
BasedOnStyle: Google
|
BasedOnStyle: Google
|
||||||
# clang-format on
|
|
||||||
AlignAfterOpenBracket: AlwaysBreak
|
AlignAfterOpenBracket: AlwaysBreak
|
||||||
AlignArrayOfStructures: Left
|
AlignArrayOfStructures: Left
|
||||||
AlignConsecutiveAssignments: None
|
AlignConsecutiveAssignments: None
|
||||||
|
|
|
@ -85,7 +85,7 @@ endif()
|
||||||
set(
|
set(
|
||||||
PUBLIC_HEADERS
|
PUBLIC_HEADERS
|
||||||
src/qtkwidget.h
|
src/qtkwidget.h
|
||||||
src/abstractscene.h
|
src/scene.h
|
||||||
src/camera3d.h
|
src/camera3d.h
|
||||||
src/mesh.h
|
src/mesh.h
|
||||||
src/meshrenderer.h
|
src/meshrenderer.h
|
||||||
|
@ -99,7 +99,7 @@ set(
|
||||||
set(
|
set(
|
||||||
SOURCE_FILES
|
SOURCE_FILES
|
||||||
src/qtkwidget.cpp
|
src/qtkwidget.cpp
|
||||||
src/abstractscene.cpp
|
src/scene.cpp
|
||||||
src/camera3d.cpp
|
src/camera3d.cpp
|
||||||
src/input.cpp
|
src/input.cpp
|
||||||
src/input.h
|
src/input.h
|
||||||
|
@ -118,7 +118,8 @@ include(GenerateExportHeader)
|
||||||
add_library(qtk-widget STATIC ${PUBLIC_HEADERS} ${SOURCE_FILES})
|
add_library(qtk-widget STATIC ${PUBLIC_HEADERS} ${SOURCE_FILES})
|
||||||
target_include_directories(qtk-widget PRIVATE src/ app/)
|
target_include_directories(qtk-widget PRIVATE src/ app/)
|
||||||
|
|
||||||
set_target_properties(qtk-widget PROPERTIES
|
set_target_properties(
|
||||||
|
qtk-widget PROPERTIES
|
||||||
PUBLIC_HEADER "${PUBLIC_HEADERS}"
|
PUBLIC_HEADER "${PUBLIC_HEADERS}"
|
||||||
VERSION ${PROJECT_VERSION}
|
VERSION ${PROJECT_VERSION}
|
||||||
)
|
)
|
||||||
|
@ -144,7 +145,8 @@ if(WIN32)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Install files
|
# Install files
|
||||||
install(TARGETS qtk-widget
|
install(
|
||||||
|
TARGETS qtk-widget
|
||||||
# Associate qtk-widget target with qtk-export
|
# Associate qtk-widget target with qtk-export
|
||||||
EXPORT qtk-export
|
EXPORT qtk-export
|
||||||
# <prefix>/bin on DLL systems and <prefix>/lib on non-dll systems
|
# <prefix>/bin on DLL systems and <prefix>/lib on non-dll systems
|
||||||
|
@ -157,7 +159,8 @@ install(TARGETS qtk-widget
|
||||||
# Install export
|
# Install export
|
||||||
# qtkTargets.cmake will only be installed when one of the CONFIGURATIONS is installed
|
# qtkTargets.cmake will only be installed when one of the CONFIGURATIONS is installed
|
||||||
# + The generated import will only reference that qtk configuration
|
# + The generated import will only reference that qtk configuration
|
||||||
install(EXPORT qtk-export
|
install(
|
||||||
|
EXPORT qtk-export
|
||||||
FILE qtkTargets.cmake
|
FILE qtkTargets.cmake
|
||||||
CONFIGURATIONS Debug|Release
|
CONFIGURATIONS Debug|Release
|
||||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/cmake
|
DESTINATION ${CMAKE_INSTALL_PREFIX}/cmake
|
||||||
|
@ -175,9 +178,14 @@ configure_file(
|
||||||
)
|
)
|
||||||
|
|
||||||
# Add our Qt resources.qrc file to our application
|
# Add our Qt resources.qrc file to our application
|
||||||
set(QTK_APP_SOURCES app/main.cpp
|
set(
|
||||||
app/examplescene.cpp app/examplescene.h
|
QTK_APP_SOURCES
|
||||||
app/mainwindow.cpp app/mainwindow.h app/mainwindow.ui
|
app/main.cpp
|
||||||
|
app/examplescene.cpp
|
||||||
|
app/examplescene.h
|
||||||
|
app/mainwindow.cpp
|
||||||
|
app/mainwindow.h
|
||||||
|
app/mainwindow.ui
|
||||||
app/resourcemanager.h
|
app/resourcemanager.h
|
||||||
src/qtkresources.h.in
|
src/qtkresources.h.in
|
||||||
)
|
)
|
||||||
|
@ -189,13 +197,15 @@ target_include_directories(qtk-main PRIVATE src/ app/)
|
||||||
# Link qtk-main executable to main qtk-widget library
|
# Link qtk-main executable to main qtk-widget library
|
||||||
target_link_libraries(qtk-main PUBLIC qtk-widget)
|
target_link_libraries(qtk-main PUBLIC qtk-widget)
|
||||||
|
|
||||||
set_target_properties(qtk-main PROPERTIES
|
set_target_properties(
|
||||||
|
qtk-main PROPERTIES
|
||||||
WIN32_EXECUTABLE TRUE
|
WIN32_EXECUTABLE TRUE
|
||||||
MACOSX_BUNDLE TRUE
|
MACOSX_BUNDLE TRUE
|
||||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||||
)
|
)
|
||||||
install(TARGETS qtk-main
|
install(
|
||||||
|
TARGETS qtk-main
|
||||||
BUNDLE DESTINATION .
|
BUNDLE DESTINATION .
|
||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
)
|
)
|
||||||
|
@ -206,7 +216,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)
|
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)
|
file(TO_NATIVE_PATH "${qt6_install_prefix}/bin" qt6_install_prefix)
|
||||||
if(TARGET Qt6::windeployqt)
|
if(TARGET Qt6::windeployqt)
|
||||||
add_custom_command(TARGET qtk-main
|
add_custom_command(
|
||||||
|
TARGET qtk-main
|
||||||
POST_BUILD
|
POST_BUILD
|
||||||
COMMAND set PATH=%PATH%$<SEMICOLON>${qt6_install_prefix}
|
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>"
|
COMMAND Qt6::windeployqt --dir "${CMAKE_BINARY_DIR}/windeployqt" "$<TARGET_FILE_DIR:qtk-main>/$<TARGET_FILE_NAME:qtk-main>"
|
||||||
|
|
37
README.md
37
README.md
|
@ -2,7 +2,6 @@
|
||||||
[![All Builds](https://github.com/shaunrd0/qtk/actions/workflows/all-builds.yml/badge.svg)](https://github.com/shaunrd0/qtk/actions/workflows/all-builds.yml)
|
[![All Builds](https://github.com/shaunrd0/qtk/actions/workflows/all-builds.yml/badge.svg)](https://github.com/shaunrd0/qtk/actions/workflows/all-builds.yml)
|
||||||
[![Linting](https://github.com/shaunrd0/qtk/actions/workflows/linting.yml/badge.svg)](https://github.com/shaunrd0/qtk/actions/workflows/linting.yml)
|
[![Linting](https://github.com/shaunrd0/qtk/actions/workflows/linting.yml/badge.svg)](https://github.com/shaunrd0/qtk/actions/workflows/linting.yml)
|
||||||
|
|
||||||
Practice project for learning about using OpenGL in Qt widget applications.
|
|
||||||
Model loader using [Assimp](https://assimp.org/) within a Qt widget application.
|
Model loader using [Assimp](https://assimp.org/) within a Qt widget application.
|
||||||
|
|
||||||
You can import your own models within `app/examplescene.cpp`, inside the
|
You can import your own models within `app/examplescene.cpp`, inside the
|
||||||
|
@ -12,6 +11,41 @@ happen in `ExampleScene::update()`.
|
||||||
To get textures loading on models look into [material files](http://www.paulbourke.net/dataformats/mtl/)
|
To get textures loading on models look into [material files](http://www.paulbourke.net/dataformats/mtl/)
|
||||||
and see some examples in the `resources/models/` directory.
|
and see some examples in the `resources/models/` directory.
|
||||||
|
|
||||||
|
The syntax for adding shapes and models is seen in the example below.
|
||||||
|
This would result in a scene with a red cube and a miniature spartan model placed on top.
|
||||||
|
|
||||||
|
```C++
|
||||||
|
// From: qtk/app/examplescene.cpp
|
||||||
|
|
||||||
|
void ExampleScene::init() {
|
||||||
|
// Add a skybox to the scene using default cube map images and settings.
|
||||||
|
setSkybox(new Qtk::Skybox("Skybox"));
|
||||||
|
|
||||||
|
/* Create a red cube with a mini master chief on top. */
|
||||||
|
auto myCube = new MeshRenderer("My cube", Cube(Qtk::QTK_DRAW_ELEMENTS));
|
||||||
|
myCube->setColor(RED);
|
||||||
|
mMeshes.push_back(myCube);
|
||||||
|
|
||||||
|
auto mySpartan = new Model("My spartan", ":/models/spartan/spartan.obj");
|
||||||
|
mySpartan->getTransform().setTranslation(0.0f, 0.5f, 0.0f);
|
||||||
|
mySpartan->getTransform().setScale(0.5f);
|
||||||
|
mModels.push_back(mySpartan);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If we want to make our spartan spin, we need to apply rotation in `update`
|
||||||
|
|
||||||
|
```C++
|
||||||
|
// From: qtk/app/examplescene.cpp
|
||||||
|
|
||||||
|
void ExampleScene::update() {
|
||||||
|
auto mySpartan = Model::getInstance("My spartan");
|
||||||
|
mySpartan->getTransform().rotate(0.75f, 0.0f, 1.0f, 0.0f);
|
||||||
|
|
||||||
|
auto myCube = MeshRenderer::getInstance("My cube");
|
||||||
|
myCube->getTransform().rotate(-0.75f, 0.0f, 1.0f, 0.0f);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Source Builds
|
### Source Builds
|
||||||
|
|
||||||
|
@ -132,7 +166,6 @@ Spartan with normals -
|
||||||
|
|
||||||
### QtkWidget in Qt Creator
|
### QtkWidget in Qt Creator
|
||||||
|
|
||||||
The `QtkWidget` class is exported as a shared library for use in Qt Creator's design mode.
|
|
||||||
We can add more QtkWidgets to view and render the scene from multiple perspectives.
|
We can add more QtkWidgets to view and render the scene from multiple perspectives.
|
||||||
There is still some work to be done here, so there isn't a builtin way to add an additional view within the application.
|
There is still some work to be done here, so there isn't a builtin way to add an additional view within the application.
|
||||||
|
|
||||||
|
|
|
@ -6,12 +6,12 @@
|
||||||
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
|
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
|
||||||
##############################################################################*/
|
##############################################################################*/
|
||||||
|
|
||||||
#include <abstractscene.h>
|
|
||||||
#include <camera3d.h>
|
#include <camera3d.h>
|
||||||
#include <examplescene.h>
|
#include <examplescene.h>
|
||||||
#include <meshrenderer.h>
|
#include <meshrenderer.h>
|
||||||
#include <model.h>
|
#include <model.h>
|
||||||
#include <resourcemanager.h>
|
#include <resourcemanager.h>
|
||||||
|
#include <scene.h>
|
||||||
#include <texture.h>
|
#include <texture.h>
|
||||||
|
|
||||||
using namespace Qtk;
|
using namespace Qtk;
|
||||||
|
@ -21,8 +21,8 @@ using namespace Qtk;
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
ExampleScene::ExampleScene() {
|
ExampleScene::ExampleScene() {
|
||||||
Camera().transform().setTranslation(0.0f, 0.0f, 20.0f);
|
getCamera().getTransform().setTranslation(0.0f, 0.0f, 20.0f);
|
||||||
Camera().transform().setRotation(-5.0f, 0.0f, 1.0f, 0.0f);
|
getCamera().getTransform().setRotation(-5.0f, 0.0f, 1.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExampleScene::~ExampleScene() {
|
ExampleScene::~ExampleScene() {
|
||||||
|
@ -44,50 +44,152 @@ ExampleScene::~ExampleScene() {
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
void ExampleScene::init() {
|
void ExampleScene::init() {
|
||||||
auto * sb = new Qtk::Skybox("Skybox");
|
// Add a skybox to the scene using default cube map images and settings.
|
||||||
setSkybox(sb);
|
setSkybox(new Qtk::Skybox("Skybox"));
|
||||||
|
|
||||||
// Initialize Phong example cube
|
/* Create a red cube with a mini master chief on top. */
|
||||||
|
auto myCube = new MeshRenderer("My cube", Cube(Qtk::QTK_DRAW_ELEMENTS));
|
||||||
|
myCube->setColor(RED);
|
||||||
|
mMeshes.push_back(myCube);
|
||||||
|
|
||||||
|
auto mySpartan = new Model("My spartan", ":/models/spartan/spartan.obj");
|
||||||
|
mySpartan->getTransform().setTranslation(0.0f, 0.5f, 0.0f);
|
||||||
|
mySpartan->getTransform().setScale(0.5f);
|
||||||
|
mModels.push_back(mySpartan);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Create simple shapes using MeshRenderer class and data in mesh.h
|
||||||
|
|
||||||
|
mMeshes.push_back(
|
||||||
|
new Qtk::MeshRenderer("rightTriangle", Triangle(QTK_DRAW_ELEMENTS)));
|
||||||
|
mMeshes.back()->getTransform().setTranslation(-5.0f, 0.0f, -2.0f);
|
||||||
|
|
||||||
|
mMeshes.push_back(
|
||||||
|
new Qtk::MeshRenderer("centerCube", Cube(QTK_DRAW_ELEMENTS)));
|
||||||
|
mMeshes.back()->getTransform().setTranslation(-7.0f, 0.0f, -2.0f);
|
||||||
|
|
||||||
|
mMeshes.push_back(
|
||||||
|
new Qtk::MeshRenderer("leftTriangle", Triangle(QTK_DRAW_ELEMENTS)));
|
||||||
|
mMeshes.back()->getTransform().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()->getTransform().setTranslation(-7.0f, 2.0f, -2.0f);
|
||||||
|
mMeshes.back()->getTransform().scale(0.25f);
|
||||||
|
|
||||||
|
mMeshes.push_back(
|
||||||
|
new Qtk::MeshRenderer("bottomTriangle", Triangle(QTK_DRAW_ELEMENTS)));
|
||||||
|
mMeshes.back()->getTransform().setTranslation(-7.0f, -2.0f, -2.0f);
|
||||||
|
mMeshes.back()->getTransform().scale(0.25f);
|
||||||
|
mMeshes.back()->setDrawType(GL_LINE_LOOP);
|
||||||
|
mMeshes.back()->setColor(GREEN);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// 3D Model loading
|
||||||
|
|
||||||
|
mModels.push_back(
|
||||||
|
new Qtk::Model("backpack", ":/models/backpack/backpack.obj"));
|
||||||
|
// Sometimes model textures need flipped in certain directions
|
||||||
|
mModels.back()->flipTexture("diffuse.jpg", false, true);
|
||||||
|
mModels.back()->getTransform().setTranslation(0.0f, 0.0f, -10.0f);
|
||||||
|
|
||||||
|
mModels.push_back(new Qtk::Model("bird", ":/models/bird/bird.obj"));
|
||||||
|
mModels.back()->getTransform().setTranslation(2.0f, 2.0f, -10.0f);
|
||||||
|
// Sometimes the models are very large
|
||||||
|
mModels.back()->getTransform().scale(0.0025f);
|
||||||
|
mModels.back()->getTransform().rotate(-110.0f, 0.0f, 1.0f, 0.0f);
|
||||||
|
|
||||||
|
mModels.push_back(new Qtk::Model("lion", ":/models/lion/lion.obj"));
|
||||||
|
mModels.back()->getTransform().setTranslation(-3.0f, -1.0f, -10.0f);
|
||||||
|
mModels.back()->getTransform().scale(0.15f);
|
||||||
|
|
||||||
|
mModels.push_back(
|
||||||
|
new Qtk::Model("alien", ":/models/alien-hominid/alien.obj"));
|
||||||
|
mModels.back()->getTransform().setTranslation(2.0f, -1.0f, -5.0f);
|
||||||
|
mModels.back()->getTransform().scale(0.15f);
|
||||||
|
|
||||||
|
mModels.push_back(new Qtk::Model("scythe", ":/models/scythe/scythe.obj"));
|
||||||
|
mModels.back()->getTransform().setTranslation(-6.0f, 0.0f, -10.0f);
|
||||||
|
mModels.back()->getTransform().rotate(-90.0f, 1.0f, 0.0f, 0.0f);
|
||||||
|
mModels.back()->getTransform().rotate(90.0f, 0.0f, 1.0f, 0.0f);
|
||||||
|
|
||||||
|
mModels.push_back(
|
||||||
|
new Qtk::Model("masterChief", ":/models/spartan/spartan.obj"));
|
||||||
|
mModels.back()->getTransform().setTranslation(-1.5f, 0.5f, -2.0f);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Simple cube lighting examples.
|
||||||
|
|
||||||
|
/* Phong lighting example on a basic cube. */
|
||||||
mTestPhong = new Qtk::MeshRenderer("phong", Qtk::Cube());
|
mTestPhong = new Qtk::MeshRenderer("phong", Qtk::Cube());
|
||||||
mTestPhong->mTransform.setTranslation(3.0f, 0.0f, -2.0f);
|
mTestPhong->getTransform().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");
|
mTestPhong->setShaders(":/solid-phong.vert", ":/solid-phong.frag");
|
||||||
|
|
||||||
// You no longer need to manually bind shader program.
|
// For example this would technically not be efficient, because each one of
|
||||||
// + But, you can still bind it if you want to.
|
// these calls will bind, set, release. We could instead bind, set N uniforms,
|
||||||
|
// and release when we are finished.
|
||||||
// mTestPhong->bindShaders();
|
// mTestPhong->bindShaders();
|
||||||
mTestPhong->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
|
mTestPhong->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
|
||||||
mTestPhong->setUniform("uLightColor", QVector3D(1.0f, 1.0f, 1.0f));
|
mTestPhong->setUniform("uLightColor", QVector3D(1.0f, 1.0f, 1.0f));
|
||||||
mTestPhong->setUniform("uAmbientStrength", 0.2f);
|
mTestPhong->setUniform("uAmbientStrength", 0.2f);
|
||||||
mTestPhong->setUniform("uSpecularStrength", 0.50f);
|
mTestPhong->setUniform("uSpecularStrength", 0.50f);
|
||||||
mTestPhong->setUniform("uSpecularShine", 256);
|
mTestPhong->setUniform("uSpecularShine", 256);
|
||||||
mTestPhong->reallocateNormals(mTestPhong->getNormals());
|
|
||||||
// mTestPhong->releaseShaders();
|
// 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.
|
||||||
|
|
||||||
// Initialize Ambient example cube
|
// 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()->getTransform().setTranslation(3.0f, 2.0f, -2.0f);
|
||||||
|
mMeshes.back()->getTransform().scale(0.25f);
|
||||||
|
|
||||||
|
/* Example of a cube with no lighting applied */
|
||||||
|
mMeshes.push_back(new Qtk::MeshRenderer("noLight", Cube(QTK_DRAW_ELEMENTS)));
|
||||||
|
mMeshes.back()->getTransform().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 = new Qtk::MeshRenderer("ambient", Cube());
|
||||||
mTestAmbient->mTransform.setTranslation(7.0f, 0.0f, -2.0f);
|
mTestAmbient->getTransform().setTranslation(7.0f, 0.0f, -2.0f);
|
||||||
mTestAmbient->setShaders(":/solid-ambient.vert", ":/solid-ambient.frag");
|
mTestAmbient->setShaders(":/solid-ambient.vert", ":/solid-ambient.frag");
|
||||||
mTestAmbient->init();
|
// Changing these uniform values will alter lighting effects.
|
||||||
mTestAmbient->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
|
mTestAmbient->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
|
||||||
mTestAmbient->setUniform("uLightColor", QVector3D(1.0f, 1.0f, 1.0f));
|
mTestAmbient->setUniform("uLightColor", QVector3D(1.0f, 1.0f, 1.0f));
|
||||||
mTestAmbient->setUniform("uAmbientStrength", 0.2f);
|
mTestAmbient->setUniform("uAmbientStrength", 0.2f);
|
||||||
mTestAmbient->reallocateNormals(mTestAmbient->getNormals());
|
mTestAmbient->reallocateNormals(mTestAmbient->getNormals());
|
||||||
|
// No light source needed for this lighting technique
|
||||||
|
|
||||||
// Initialize Diffuse example cube
|
/* Initialize Diffuse example cube */
|
||||||
mTestDiffuse = new Qtk::MeshRenderer("diffuse", Cube());
|
mTestDiffuse = new Qtk::MeshRenderer("diffuse", Cube());
|
||||||
mTestDiffuse->mTransform.setTranslation(9.0f, 0.0f, -2.0f);
|
mTestDiffuse->getTransform().setTranslation(9.0f, 0.0f, -2.0f);
|
||||||
mTestDiffuse->setShaders(":/solid-diffuse.vert", ":/solid-diffuse.frag");
|
mTestDiffuse->setShaders(":/solid-diffuse.vert", ":/solid-diffuse.frag");
|
||||||
mTestDiffuse->init();
|
|
||||||
mTestDiffuse->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
|
mTestDiffuse->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
|
||||||
mTestDiffuse->setUniform("uLightColor", QVector3D(1.0f, 1.0f, 1.0f));
|
mTestDiffuse->setUniform("uLightColor", QVector3D(1.0f, 1.0f, 1.0f));
|
||||||
mTestDiffuse->setUniform("uAmbientStrength", 0.2f);
|
mTestDiffuse->setUniform("uAmbientStrength", 0.2f);
|
||||||
mTestDiffuse->reallocateNormals(mTestDiffuse->getNormals());
|
mTestDiffuse->reallocateNormals(mTestDiffuse->getNormals());
|
||||||
|
|
||||||
// Initialize Specular example cube
|
// Diffuse lighting example light source. This is just for visual reference.
|
||||||
|
mMeshes.push_back(
|
||||||
|
new Qtk::MeshRenderer("diffuseLight", Triangle(QTK_DRAW_ELEMENTS)));
|
||||||
|
mMeshes.back()->getTransform().setTranslation(9.0f, 2.0f, -2.0f);
|
||||||
|
mMeshes.back()->getTransform().scale(0.25f);
|
||||||
|
|
||||||
|
/* Initialize Specular example cube */
|
||||||
mTestSpecular = new Qtk::MeshRenderer("specular", Cube());
|
mTestSpecular = new Qtk::MeshRenderer("specular", Cube());
|
||||||
mTestSpecular->mTransform.setTranslation(11.0f, 0.0f, -2.0f);
|
mTestSpecular->getTransform().setTranslation(11.0f, 0.0f, -2.0f);
|
||||||
mTestSpecular->setShaders(":/solid-specular.vert", ":/solid-specular.frag");
|
mTestSpecular->setShaders(":/solid-specular.vert", ":/solid-specular.frag");
|
||||||
mTestSpecular->init();
|
|
||||||
mTestSpecular->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
|
mTestSpecular->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
|
||||||
mTestSpecular->setUniform("uLightColor", QVector3D(1.0f, 1.0f, 1.0f));
|
mTestSpecular->setUniform("uLightColor", QVector3D(1.0f, 1.0f, 1.0f));
|
||||||
mTestSpecular->setUniform("uAmbientStrength", 0.2f);
|
mTestSpecular->setUniform("uAmbientStrength", 0.2f);
|
||||||
|
@ -95,105 +197,18 @@ void ExampleScene::init() {
|
||||||
mTestSpecular->setUniform("uSpecularShine", 256);
|
mTestSpecular->setUniform("uSpecularShine", 256);
|
||||||
mTestSpecular->reallocateNormals(mTestSpecular->getNormals());
|
mTestSpecular->reallocateNormals(mTestSpecular->getNormals());
|
||||||
|
|
||||||
|
// Specular lighting example light source. This is just for visual reference.
|
||||||
//
|
|
||||||
// Model loading
|
|
||||||
|
|
||||||
mModels.push_back(
|
|
||||||
new Qtk::Model("backpack", ":/models/backpack/backpack.obj"));
|
|
||||||
// Sometimes model textures need flipped in certain directions
|
|
||||||
mModels.back()->flipTexture("diffuse.jpg", false, true);
|
|
||||||
mModels.back()->mTransform.setTranslation(0.0f, 0.0f, -10.0f);
|
|
||||||
|
|
||||||
mModels.push_back(new Qtk::Model("bird", ":/models/bird/bird.obj"));
|
|
||||||
mModels.back()->mTransform.setTranslation(2.0f, 2.0f, -10.0f);
|
|
||||||
// Sometimes the models are very large
|
|
||||||
mModels.back()->mTransform.scale(0.0025f);
|
|
||||||
mModels.back()->mTransform.rotate(-110.0f, 0.0f, 1.0f, 0.0f);
|
|
||||||
|
|
||||||
mModels.push_back(new Qtk::Model("lion", ":/models/lion/lion.obj"));
|
|
||||||
mModels.back()->mTransform.setTranslation(-3.0f, -1.0f, -10.0f);
|
|
||||||
mModels.back()->mTransform.scale(0.15f);
|
|
||||||
|
|
||||||
mModels.push_back(
|
|
||||||
new Qtk::Model("alien", ":/models/alien-hominid/alien.obj"));
|
|
||||||
mModels.back()->mTransform.setTranslation(2.0f, -1.0f, -5.0f);
|
|
||||||
mModels.back()->mTransform.scale(0.15f);
|
|
||||||
|
|
||||||
mModels.push_back(new Qtk::Model("scythe", ":/models/scythe/scythe.obj"));
|
|
||||||
mModels.back()->mTransform.setTranslation(-6.0f, 0.0f, -10.0f);
|
|
||||||
mModels.back()->mTransform.rotate(-90.0f, 1.0f, 0.0f, 0.0f);
|
|
||||||
mModels.back()->mTransform.rotate(90.0f, 0.0f, 1.0f, 0.0f);
|
|
||||||
|
|
||||||
mModels.push_back(
|
|
||||||
new Qtk::Model("masterChief", ":/models/spartan/spartan.obj"));
|
|
||||||
mModels.back()->mTransform.setTranslation(-1.5f, 0.5f, -2.0f);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Building example mesh objects
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
mMeshes.back()->mTransform.scale(0.25f);
|
|
||||||
// This function changes values we have allocated in a buffer, so init() after
|
|
||||||
mMeshes.back()->setColor(GREEN);
|
|
||||||
|
|
||||||
mModels.push_back(new Qtk::Model(
|
|
||||||
"alienTest", ":/models/alien-hominid/alien.obj", ":/model-specular.vert",
|
|
||||||
":/model-specular.frag"));
|
|
||||||
mModels.back()->mTransform.setTranslation(3.0f, -1.0f, 10.0f);
|
|
||||||
mModels.back()->mTransform.scale(0.15f);
|
|
||||||
mModels.back()->setUniform("uMaterial.ambient", QVector3D(1.0f, 1.0f, 1.0f));
|
|
||||||
mModels.back()->setUniform("uMaterial.diffuse", QVector3D(1.0f, 1.0f, 1.0f));
|
|
||||||
mModels.back()->setUniform("uMaterial.specular", QVector3D(1.0f, 1.0f, 1.0f));
|
|
||||||
mModels.back()->setUniform("uMaterial.ambientStrength", 0.8f);
|
|
||||||
mModels.back()->setUniform("uMaterial.diffuseStrength", 0.8f);
|
|
||||||
mModels.back()->setUniform("uMaterial.specularStrength", 1.0f);
|
|
||||||
mModels.back()->setUniform("uMaterial.shine", 32.0f);
|
|
||||||
|
|
||||||
mModels.back()->setUniform("uLight.ambient", QVector3D(1.0f, 1.0f, 1.0f));
|
|
||||||
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(
|
mMeshes.push_back(
|
||||||
new Qtk::MeshRenderer("spartanTestLight", Triangle(QTK_DRAW_ELEMENTS)));
|
new Qtk::MeshRenderer("specularLight", Triangle(QTK_DRAW_ELEMENTS)));
|
||||||
mMeshes.back()->mTransform.setTranslation(1.0f, 1.5f, 10.0f);
|
mMeshes.back()->getTransform().setTranslation(11.0f, 2.0f, -2.0f);
|
||||||
mMeshes.back()->mTransform.scale(0.25f);
|
mMeshes.back()->getTransform().scale(0.25f);
|
||||||
// This function changes values we have allocated in a buffer, so init() after
|
|
||||||
mMeshes.back()->setColor(GREEN);
|
|
||||||
|
|
||||||
mModels.push_back(new Qtk::Model(
|
|
||||||
"spartanTest", ":/models/spartan/spartan.obj", ":/model-normals.vert",
|
|
||||||
":/model-normals.frag"));
|
|
||||||
mModels.back()->mTransform.setTranslation(0.0f, -1.0f, 10.0f);
|
|
||||||
mModels.back()->mTransform.scale(2.0f);
|
|
||||||
mModels.back()->setUniform("uMaterial.ambient", QVector3D(1.0f, 1.0f, 1.0f));
|
|
||||||
mModels.back()->setUniform("uMaterial.diffuse", QVector3D(1.0f, 1.0f, 1.0f));
|
|
||||||
mModels.back()->setUniform("uMaterial.specular", QVector3D(1.0f, 1.0f, 1.0f));
|
|
||||||
mModels.back()->setUniform("uMaterial.ambientStrength", 1.0f);
|
|
||||||
mModels.back()->setUniform("uMaterial.diffuseStrength", 1.0f);
|
|
||||||
mModels.back()->setUniform("uMaterial.specularStrength", 1.0f);
|
|
||||||
mModels.back()->setUniform("uMaterial.shine", 128.0f);
|
|
||||||
mModels.back()->setUniform("uLight.ambient", QVector3D(1.0f, 1.0f, 1.0f));
|
|
||||||
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
|
|
||||||
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);
|
|
||||||
// This function changes values we have allocated in a buffer, so init() after
|
|
||||||
mMeshes.back()->setColor(GREEN);
|
|
||||||
|
|
||||||
|
/* Test basic cube with phong.vert and phong.frag shaders */
|
||||||
mMeshes.push_back(new Qtk::MeshRenderer("testPhong", Cube(QTK_DRAW_ARRAYS)));
|
mMeshes.push_back(new Qtk::MeshRenderer("testPhong", Cube(QTK_DRAW_ARRAYS)));
|
||||||
mMeshes.back()->mTransform.setTranslation(5.0f, 0.0f, 10.0f);
|
mMeshes.back()->getTransform().setTranslation(5.0f, 0.0f, 10.0f);
|
||||||
mMeshes.back()->setShaders(":/phong.vert", ":/phong.frag");
|
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()->setColor(QVector3D(0.0f, 0.25f, 0.0f));
|
||||||
mMeshes.back()->reallocateNormals(mMeshes.back()->getNormals());
|
mMeshes.back()->reallocateNormals(mMeshes.back()->getNormals());
|
||||||
|
|
||||||
|
@ -209,50 +224,84 @@ void ExampleScene::init() {
|
||||||
mMeshes.back()->setUniform("uLight.specular", QVector3D(0.62f, 0.55f, 0.37f));
|
mMeshes.back()->setUniform("uLight.specular", QVector3D(0.62f, 0.55f, 0.37f));
|
||||||
mMeshes.back()->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
|
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()->getTransform().setTranslation(5.0f, 1.25f, 10.0f);
|
||||||
|
mMeshes.back()->getTransform().scale(0.25f);
|
||||||
|
mMeshes.back()->setDrawType(GL_LINE_LOOP);
|
||||||
|
mMeshes.back()->setColor(RED);
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Create simple shapes using MeshRenderer class and data in mesh.h
|
// Building more complex objects for showing examples of lighting techniques
|
||||||
|
|
||||||
mMeshes.push_back(
|
/* Test alien Model with phong lighting and specular mapping. */
|
||||||
new Qtk::MeshRenderer("rightTriangle", Triangle(QTK_DRAW_ELEMENTS)));
|
mModels.push_back(new Qtk::Model(
|
||||||
mMeshes.back()->mTransform.setTranslation(-5.0f, 0.0f, -2.0f);
|
"alienTest", ":/models/alien-hominid/alien.obj", ":/model-specular.vert",
|
||||||
|
":/model-specular.frag"));
|
||||||
|
mModels.back()->getTransform().setTranslation(3.0f, -1.0f, 10.0f);
|
||||||
|
mModels.back()->getTransform().scale(0.15f);
|
||||||
|
mModels.back()->setUniform("uMaterial.ambient", QVector3D(1.0f, 1.0f, 1.0f));
|
||||||
|
mModels.back()->setUniform("uMaterial.diffuse", QVector3D(1.0f, 1.0f, 1.0f));
|
||||||
|
mModels.back()->setUniform("uMaterial.specular", QVector3D(1.0f, 1.0f, 1.0f));
|
||||||
|
mModels.back()->setUniform("uMaterial.ambientStrength", 0.8f);
|
||||||
|
mModels.back()->setUniform("uMaterial.diffuseStrength", 0.8f);
|
||||||
|
mModels.back()->setUniform("uMaterial.specularStrength", 1.0f);
|
||||||
|
mModels.back()->setUniform("uMaterial.shine", 32.0f);
|
||||||
|
|
||||||
mMeshes.push_back(
|
mModels.back()->setUniform("uLight.ambient", QVector3D(1.0f, 1.0f, 1.0f));
|
||||||
new Qtk::MeshRenderer("centerCube", Cube(QTK_DRAW_ELEMENTS)));
|
mModels.back()->setUniform("uLight.diffuse", QVector3D(1.0f, 1.0f, 1.0f));
|
||||||
mMeshes.back()->mTransform.setTranslation(-7.0f, 0.0f, -2.0f);
|
mModels.back()->setUniform("uLight.specular", QVector3D(1.0f, 1.0f, 1.0f));
|
||||||
|
|
||||||
mMeshes.push_back(
|
// Light source for alienTest object.
|
||||||
new Qtk::MeshRenderer("leftTriangle", Triangle(QTK_DRAW_ELEMENTS)));
|
mMeshes.push_back(new Qtk::MeshRenderer(
|
||||||
mMeshes.back()->mTransform.setTranslation(-9.0f, 0.0f, -2.0f);
|
"alienTestLight", Triangle(Qtk::QTK_DRAW_ELEMENTS)));
|
||||||
mMeshes.back()->setDrawType(GL_LINE_LOOP);
|
mMeshes.back()->getTransform().setTranslation(4.0f, 1.5f, 10.0f);
|
||||||
|
mMeshes.back()->getTransform().scale(0.25f);
|
||||||
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
|
// This function changes values we have allocated in a buffer, so init() after
|
||||||
mMeshes.back()->setColor(GREEN);
|
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"));
|
||||||
|
mModels.back()->getTransform().setTranslation(0.0f, -1.0f, 10.0f);
|
||||||
|
mModels.back()->getTransform().scale(2.0f);
|
||||||
|
mModels.back()->setUniform("uMaterial.ambient", QVector3D(1.0f, 1.0f, 1.0f));
|
||||||
|
mModels.back()->setUniform("uMaterial.diffuse", QVector3D(1.0f, 1.0f, 1.0f));
|
||||||
|
mModels.back()->setUniform("uMaterial.specular", QVector3D(1.0f, 1.0f, 1.0f));
|
||||||
|
mModels.back()->setUniform("uMaterial.ambientStrength", 1.0f);
|
||||||
|
mModels.back()->setUniform("uMaterial.diffuseStrength", 1.0f);
|
||||||
|
mModels.back()->setUniform("uMaterial.specularStrength", 1.0f);
|
||||||
|
mModels.back()->setUniform("uMaterial.shine", 128.0f);
|
||||||
|
mModels.back()->setUniform("uLight.ambient", QVector3D(1.0f, 1.0f, 1.0f));
|
||||||
|
mModels.back()->setUniform("uLight.diffuse", QVector3D(1.0f, 1.0f, 1.0f));
|
||||||
|
mModels.back()->setUniform("uLight.specular", QVector3D(1.0f, 1.0f, 1.0f));
|
||||||
|
|
||||||
|
// Light source for spartanTest object.
|
||||||
|
mMeshes.push_back(
|
||||||
|
new Qtk::MeshRenderer("spartanTestLight", Triangle(QTK_DRAW_ELEMENTS)));
|
||||||
|
mMeshes.back()->getTransform().setTranslation(1.0f, 1.5f, 10.0f);
|
||||||
|
mMeshes.back()->getTransform().scale(0.25f);
|
||||||
|
// 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
|
// RGB Normals cube to show normals are correct with QTK_DRAW_ARRAYS
|
||||||
mMeshes.push_back(
|
mMeshes.push_back(
|
||||||
new Qtk::MeshRenderer("rgbNormalsCubeArraysTest", Cube(QTK_DRAW_ARRAYS)));
|
new Qtk::MeshRenderer("rgbNormalsCubeArraysTest", Cube(QTK_DRAW_ARRAYS)));
|
||||||
mMeshes.back()->mTransform.setTranslation(5.0f, 0.0f, 4.0f);
|
mMeshes.back()->getTransform().setTranslation(5.0f, 0.0f, 4.0f);
|
||||||
mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag");
|
mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag");
|
||||||
mMeshes.back()->reallocateNormals(mMeshes.back()->getNormals());
|
mMeshes.back()->reallocateNormals(mMeshes.back()->getNormals());
|
||||||
|
|
||||||
// RGB Normals cube to show normals are correct with QTK_DRAW_ELEMENTS_NORMALS
|
// RGB Normals cube to show normals are correct with QTK_DRAW_ELEMENTS_NORMALS
|
||||||
mMeshes.push_back(new Qtk::MeshRenderer(
|
mMeshes.push_back(new Qtk::MeshRenderer(
|
||||||
"rgbNormalsCubeElementsTest", Cube(QTK_DRAW_ELEMENTS_NORMALS)));
|
"rgbNormalsCubeElementsTest", Cube(QTK_DRAW_ELEMENTS_NORMALS)));
|
||||||
mMeshes.back()->mTransform.setTranslation(5.0f, 0.0f, 2.0f);
|
mMeshes.back()->getTransform().setTranslation(5.0f, 0.0f, 2.0f);
|
||||||
mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag");
|
mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag");
|
||||||
mMeshes.back()->reallocateNormals(mMeshes.back()->getNormals());
|
mMeshes.back()->reallocateNormals(mMeshes.back()->getNormals());
|
||||||
|
|
||||||
|
@ -260,7 +309,7 @@ void ExampleScene::init() {
|
||||||
crateTexture.setTexture(":/crate.png");
|
crateTexture.setTexture(":/crate.png");
|
||||||
Cube cube;
|
Cube cube;
|
||||||
auto * m = new MeshRenderer("Test Crate", Cube(QTK_DRAW_ARRAYS));
|
auto * m = new MeshRenderer("Test Crate", Cube(QTK_DRAW_ARRAYS));
|
||||||
m->mTransform.setTranslation(0, 0, 13);
|
m->getTransform().setTranslation(0, 0, 13);
|
||||||
m->setShaders(":/texture2d.vert", ":/texture2d.frag");
|
m->setShaders(":/texture2d.vert", ":/texture2d.frag");
|
||||||
m->setTexture(crateTexture);
|
m->setTexture(crateTexture);
|
||||||
m->setUniform("uTexture", 0);
|
m->setUniform("uTexture", 0);
|
||||||
|
@ -274,7 +323,7 @@ void ExampleScene::init() {
|
||||||
// + This is because the same position must use different UV coordinates
|
// + This is because the same position must use different UV coordinates
|
||||||
mMeshes.push_back(
|
mMeshes.push_back(
|
||||||
new Qtk::MeshRenderer("uvCubeArraysTest", Cube(QTK_DRAW_ARRAYS)));
|
new Qtk::MeshRenderer("uvCubeArraysTest", Cube(QTK_DRAW_ARRAYS)));
|
||||||
mMeshes.back()->mTransform.setTranslation(-3.0f, 0.0f, -2.0f);
|
mMeshes.back()->getTransform().setTranslation(-3.0f, 0.0f, -2.0f);
|
||||||
mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag");
|
mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag");
|
||||||
mMeshes.back()->setTexture(crateTexture);
|
mMeshes.back()->setTexture(crateTexture);
|
||||||
mMeshes.back()->setUniform("uTexture", 0);
|
mMeshes.back()->setUniform("uTexture", 0);
|
||||||
|
@ -283,7 +332,7 @@ void ExampleScene::init() {
|
||||||
// Test drawing a cube with texture coordinates using glDrawElements
|
// Test drawing a cube with texture coordinates using glDrawElements
|
||||||
mMeshes.push_back(new Qtk::MeshRenderer(
|
mMeshes.push_back(new Qtk::MeshRenderer(
|
||||||
"uvCubeElementsTest", Cube(QTK_DRAW_ELEMENTS_NORMALS)));
|
"uvCubeElementsTest", Cube(QTK_DRAW_ELEMENTS_NORMALS)));
|
||||||
mMeshes.back()->mTransform.setTranslation(-1.7f, 0.0f, -2.0f);
|
mMeshes.back()->getTransform().setTranslation(-1.7f, 0.0f, -2.0f);
|
||||||
mMeshes.back()->setTexture(":/crate.png");
|
mMeshes.back()->setTexture(":/crate.png");
|
||||||
mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag");
|
mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag");
|
||||||
mMeshes.back()->bindShaders();
|
mMeshes.back()->bindShaders();
|
||||||
|
@ -291,14 +340,14 @@ void ExampleScene::init() {
|
||||||
mMeshes.back()->reallocateNormals(mMeshes.back()->getNormals());
|
mMeshes.back()->reallocateNormals(mMeshes.back()->getNormals());
|
||||||
mMeshes.back()->reallocateTexCoords(mMeshes.back()->getTexCoords(), 3);
|
mMeshes.back()->reallocateTexCoords(mMeshes.back()->getTexCoords(), 3);
|
||||||
mMeshes.back()->releaseShaders();
|
mMeshes.back()->releaseShaders();
|
||||||
mMeshes.back()->mTransform.rotate(45.0f, 0.0f, 1.0f, 0.0f);
|
mMeshes.back()->getTransform().rotate(45.0f, 0.0f, 1.0f, 0.0f);
|
||||||
|
|
||||||
// Texturing a cube using a cube map
|
// Texturing a cube using a cube map
|
||||||
// + Cube map texturing works with both QTK_DRAW_ARRAYS and QTK_DRAW_ELEMENTS
|
// + Cube map texturing works with both QTK_DRAW_ARRAYS and QTK_DRAW_ELEMENTS
|
||||||
mMeshes.push_back(
|
mMeshes.push_back(
|
||||||
new Qtk::MeshRenderer("testCubeMap", Cube(QTK_DRAW_ELEMENTS)));
|
new Qtk::MeshRenderer("testCubeMap", Cube(QTK_DRAW_ELEMENTS)));
|
||||||
mMeshes.back()->mTransform.setTranslation(-3.0f, 1.0f, -2.0f);
|
mMeshes.back()->getTransform().setTranslation(-3.0f, 1.0f, -2.0f);
|
||||||
mMeshes.back()->mTransform.setRotation(45.0f, 0.0f, 1.0f, 0.0f);
|
mMeshes.back()->getTransform().setRotation(45.0f, 0.0f, 1.0f, 0.0f);
|
||||||
mMeshes.back()->setShaders(
|
mMeshes.back()->setShaders(
|
||||||
":/texture-cubemap.vert", ":/texture-cubemap.frag");
|
":/texture-cubemap.vert", ":/texture-cubemap.frag");
|
||||||
mMeshes.back()->setCubeMap(":/crate.png");
|
mMeshes.back()->setCubeMap(":/crate.png");
|
||||||
|
@ -309,28 +358,28 @@ void ExampleScene::init() {
|
||||||
// + Apply RGB normals shader and spin the cube for a neat effect
|
// + Apply RGB normals shader and spin the cube for a neat effect
|
||||||
mMeshes.push_back(
|
mMeshes.push_back(
|
||||||
new Qtk::MeshRenderer("rgbNormalsCube", Cube(QTK_DRAW_ARRAYS)));
|
new Qtk::MeshRenderer("rgbNormalsCube", Cube(QTK_DRAW_ARRAYS)));
|
||||||
mMeshes.back()->mTransform.setTranslation(5.0f, 2.0f, -2.0f);
|
mMeshes.back()->getTransform().setTranslation(5.0f, 2.0f, -2.0f);
|
||||||
mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag");
|
mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag");
|
||||||
mMeshes.back()->reallocateNormals(mMeshes.back()->getNormals());
|
mMeshes.back()->reallocateNormals(mMeshes.back()->getNormals());
|
||||||
|
|
||||||
// RGB Normals triangle to show normals are correct with QTK_DRAW_ARRAYS
|
// RGB Normals triangle to show normals are correct with QTK_DRAW_ARRAYS
|
||||||
mMeshes.push_back(new Qtk::MeshRenderer(
|
mMeshes.push_back(new Qtk::MeshRenderer(
|
||||||
"rgbTriangleArraysTest", Triangle(QTK_DRAW_ARRAYS)));
|
"rgbTriangleArraysTest", Triangle(QTK_DRAW_ARRAYS)));
|
||||||
mMeshes.back()->mTransform.setTranslation(7.0f, 0.0f, 2.0f);
|
mMeshes.back()->getTransform().setTranslation(7.0f, 0.0f, 2.0f);
|
||||||
mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag");
|
mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag");
|
||||||
mMeshes.back()->reallocateNormals(mMeshes.back()->getNormals());
|
mMeshes.back()->reallocateNormals(mMeshes.back()->getNormals());
|
||||||
|
|
||||||
// RGB Normals triangle to show normals are correct with QTK_DRAW_ELEMENTS
|
// RGB Normals triangle to show normals are correct with QTK_DRAW_ELEMENTS
|
||||||
mMeshes.push_back(new Qtk::MeshRenderer(
|
mMeshes.push_back(new Qtk::MeshRenderer(
|
||||||
"rgbTriangleElementsTest", Triangle(QTK_DRAW_ELEMENTS_NORMALS)));
|
"rgbTriangleElementsTest", Triangle(QTK_DRAW_ELEMENTS_NORMALS)));
|
||||||
mMeshes.back()->mTransform.setTranslation(7.0f, 0.0f, 4.0f);
|
mMeshes.back()->getTransform().setTranslation(7.0f, 0.0f, 4.0f);
|
||||||
mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag");
|
mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag");
|
||||||
mMeshes.back()->reallocateNormals(mMeshes.back()->getNormals());
|
mMeshes.back()->reallocateNormals(mMeshes.back()->getNormals());
|
||||||
|
|
||||||
// Test drawing triangle with glDrawArrays with texture coordinates
|
// Test drawing triangle with glDrawArrays with texture coordinates
|
||||||
mMeshes.push_back(
|
mMeshes.push_back(
|
||||||
new Qtk::MeshRenderer("testTriangleArraysUV", Triangle(QTK_DRAW_ARRAYS)));
|
new Qtk::MeshRenderer("testTriangleArraysUV", Triangle(QTK_DRAW_ARRAYS)));
|
||||||
mMeshes.back()->mTransform.setTranslation(-3.0f, 2.0f, -2.0f);
|
mMeshes.back()->getTransform().setTranslation(-3.0f, 2.0f, -2.0f);
|
||||||
mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag");
|
mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag");
|
||||||
|
|
||||||
mMeshes.back()->setTexture(":/crate.png");
|
mMeshes.back()->setTexture(":/crate.png");
|
||||||
|
@ -340,40 +389,16 @@ void ExampleScene::init() {
|
||||||
// Test drawing triangle with glDrawElements with texture coordinates
|
// Test drawing triangle with glDrawElements with texture coordinates
|
||||||
mMeshes.push_back(new Qtk::MeshRenderer(
|
mMeshes.push_back(new Qtk::MeshRenderer(
|
||||||
"testTriangleElementsUV", Triangle(QTK_DRAW_ELEMENTS_NORMALS)));
|
"testTriangleElementsUV", Triangle(QTK_DRAW_ELEMENTS_NORMALS)));
|
||||||
mMeshes.back()->mTransform.setTranslation(-2.5f, 0.0f, -1.0f);
|
mMeshes.back()->getTransform().setTranslation(-2.5f, 0.0f, -1.0f);
|
||||||
mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag");
|
mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag");
|
||||||
mMeshes.back()->setTexture(":/crate.png");
|
mMeshes.back()->setTexture(":/crate.png");
|
||||||
mMeshes.back()->setUniform("uTexture", 0);
|
mMeshes.back()->setUniform("uTexture", 0);
|
||||||
mMeshes.back()->reallocateTexCoords(mMeshes.back()->getTexCoords());
|
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() {
|
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();
|
Scene::draw();
|
||||||
|
|
||||||
for(const auto & model : mModels) {
|
for(const auto & model : mModels) {
|
||||||
|
@ -387,129 +412,156 @@ void ExampleScene::draw() {
|
||||||
mTestPhong->bindShaders();
|
mTestPhong->bindShaders();
|
||||||
mTestPhong->setUniform(
|
mTestPhong->setUniform(
|
||||||
"uModelInverseTransposed",
|
"uModelInverseTransposed",
|
||||||
mTestPhong->mTransform.toMatrix().normalMatrix());
|
mTestPhong->getTransform().toMatrix().normalMatrix());
|
||||||
mTestPhong->setUniform(
|
mTestPhong->setUniform(
|
||||||
"uLightPosition",
|
"uLightPosition",
|
||||||
MeshRenderer::getInstance("phongLight")->mTransform.getTranslation());
|
MeshRenderer::getInstance("phongLight")->getTransform().getTranslation());
|
||||||
mTestPhong->setUniform(
|
mTestPhong->setUniform(
|
||||||
"uCameraPosition", ExampleScene::Camera().transform().getTranslation());
|
"uCameraPosition",
|
||||||
|
ExampleScene::getCamera().getTransform().getTranslation());
|
||||||
mTestPhong->releaseShaders();
|
mTestPhong->releaseShaders();
|
||||||
mTestPhong->draw();
|
mTestPhong->draw();
|
||||||
|
|
||||||
mTestAmbient->bindShaders();
|
mTestAmbient->bindShaders();
|
||||||
mTestAmbient->setUniform(
|
mTestAmbient->setUniform(
|
||||||
"uCameraPosition", ExampleScene::Camera().transform().getTranslation());
|
"uCameraPosition",
|
||||||
|
ExampleScene::getCamera().getTransform().getTranslation());
|
||||||
mTestAmbient->releaseShaders();
|
mTestAmbient->releaseShaders();
|
||||||
mTestAmbient->draw();
|
mTestAmbient->draw();
|
||||||
|
|
||||||
mTestDiffuse->bindShaders();
|
mTestDiffuse->bindShaders();
|
||||||
mTestDiffuse->setUniform(
|
mTestDiffuse->setUniform(
|
||||||
"uModelInverseTransposed",
|
"uModelInverseTransposed",
|
||||||
mTestDiffuse->mTransform.toMatrix().normalMatrix());
|
mTestDiffuse->getTransform().toMatrix().normalMatrix());
|
||||||
mTestDiffuse->setUniform(
|
mTestDiffuse->setUniform(
|
||||||
"uLightPosition",
|
"uLightPosition", MeshRenderer::getInstance("diffuseLight")
|
||||||
MeshRenderer::getInstance("diffuseLight")->mTransform.getTranslation());
|
->getTransform()
|
||||||
|
.getTranslation());
|
||||||
mTestDiffuse->setUniform(
|
mTestDiffuse->setUniform(
|
||||||
"uCameraPosition", ExampleScene::Camera().transform().getTranslation());
|
"uCameraPosition",
|
||||||
|
ExampleScene::getCamera().getTransform().getTranslation());
|
||||||
mTestDiffuse->releaseShaders();
|
mTestDiffuse->releaseShaders();
|
||||||
mTestDiffuse->draw();
|
mTestDiffuse->draw();
|
||||||
|
|
||||||
mTestSpecular->bindShaders();
|
mTestSpecular->bindShaders();
|
||||||
mTestSpecular->setUniform(
|
mTestSpecular->setUniform(
|
||||||
"uModelInverseTransposed",
|
"uModelInverseTransposed",
|
||||||
mTestSpecular->mTransform.toMatrix().normalMatrix());
|
mTestSpecular->getTransform().toMatrix().normalMatrix());
|
||||||
mTestSpecular->setUniform(
|
mTestSpecular->setUniform(
|
||||||
"uLightPosition",
|
"uLightPosition", MeshRenderer::getInstance("specularLight")
|
||||||
MeshRenderer::getInstance("specularLight")->mTransform.getTranslation());
|
->getTransform()
|
||||||
|
.getTranslation());
|
||||||
mTestSpecular->setUniform(
|
mTestSpecular->setUniform(
|
||||||
"uCameraPosition", ExampleScene::Camera().transform().getTranslation());
|
"uCameraPosition",
|
||||||
|
ExampleScene::getCamera().getTransform().getTranslation());
|
||||||
mTestSpecular->releaseShaders();
|
mTestSpecular->releaseShaders();
|
||||||
mTestSpecular->draw();
|
mTestSpecular->draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExampleScene::update() {
|
void ExampleScene::update() {
|
||||||
auto position =
|
auto mySpartan = Model::getInstance("My spartan");
|
||||||
MeshRenderer::getInstance("alienTestLight")->mTransform.getTranslation();
|
mySpartan->getTransform().rotate(0.75f, 0.0f, 1.0f, 0.0f);
|
||||||
|
|
||||||
|
auto myCube = MeshRenderer::getInstance("My cube");
|
||||||
|
myCube->getTransform().rotate(-0.75f, 0.0f, 1.0f, 0.0f);
|
||||||
|
|
||||||
|
auto position = MeshRenderer::getInstance("alienTestLight")
|
||||||
|
->getTransform()
|
||||||
|
.getTranslation();
|
||||||
auto alien = Model::getInstance("alienTest");
|
auto alien = Model::getInstance("alienTest");
|
||||||
alien->setUniform("uLight.position", position);
|
alien->setUniform("uLight.position", position);
|
||||||
alien->setUniform(
|
alien->setUniform(
|
||||||
"uCameraPosition", ExampleScene::Camera().transform().getTranslation());
|
"uCameraPosition",
|
||||||
auto posMatrix = alien->mTransform.toMatrix();
|
ExampleScene::getCamera().getTransform().getTranslation());
|
||||||
|
auto posMatrix = alien->getTransform().toMatrix();
|
||||||
alien->setUniform("uMVP.normalMatrix", posMatrix.normalMatrix());
|
alien->setUniform("uMVP.normalMatrix", posMatrix.normalMatrix());
|
||||||
alien->setUniform("uMVP.model", posMatrix);
|
alien->setUniform("uMVP.model", posMatrix);
|
||||||
alien->setUniform("uMVP.view", ExampleScene::Camera().toMatrix());
|
alien->setUniform("uMVP.view", ExampleScene::getCamera().toMatrix());
|
||||||
alien->setUniform("uMVP.projection", ExampleScene::Projection());
|
alien->setUniform("uMVP.projection", ExampleScene::getProjectionMatrix());
|
||||||
alien->mTransform.rotate(0.75f, 0.0f, 1.0f, 0.0f);
|
alien->getTransform().rotate(0.75f, 0.0f, 1.0f, 0.0f);
|
||||||
|
|
||||||
position = MeshRenderer::getInstance("spartanTestLight")
|
position = MeshRenderer::getInstance("spartanTestLight")
|
||||||
->mTransform.getTranslation();
|
->getTransform()
|
||||||
|
.getTranslation();
|
||||||
auto spartan = Model::getInstance("spartanTest");
|
auto spartan = Model::getInstance("spartanTest");
|
||||||
spartan->setUniform("uLight.position", position);
|
spartan->setUniform("uLight.position", position);
|
||||||
spartan->setUniform(
|
spartan->setUniform(
|
||||||
"uCameraPosition", ExampleScene::Camera().transform().getTranslation());
|
"uCameraPosition",
|
||||||
posMatrix = spartan->mTransform.toMatrix();
|
ExampleScene::getCamera().getTransform().getTranslation());
|
||||||
|
posMatrix = spartan->getTransform().toMatrix();
|
||||||
spartan->setUniform("uMVP.normalMatrix", posMatrix.normalMatrix());
|
spartan->setUniform("uMVP.normalMatrix", posMatrix.normalMatrix());
|
||||||
spartan->setUniform("uMVP.model", posMatrix);
|
spartan->setUniform("uMVP.model", posMatrix);
|
||||||
spartan->setUniform("uMVP.view", ExampleScene::Camera().toMatrix());
|
spartan->setUniform("uMVP.view", ExampleScene::getCamera().toMatrix());
|
||||||
spartan->setUniform("uMVP.projection", ExampleScene::Projection());
|
spartan->setUniform("uMVP.projection", ExampleScene::getProjectionMatrix());
|
||||||
spartan->mTransform.rotate(0.75f, 0.0f, 1.0f, 0.0f);
|
spartan->getTransform().rotate(0.75f, 0.0f, 1.0f, 0.0f);
|
||||||
|
|
||||||
auto phong = MeshRenderer::getInstance("testPhong");
|
auto phong = MeshRenderer::getInstance("testPhong");
|
||||||
phong->mTransform.rotate(0.75f, 1.0f, 0.5f, 0.0f);
|
phong->getTransform().rotate(0.75f, 1.0f, 0.5f, 0.0f);
|
||||||
phong->bindShaders();
|
phong->bindShaders();
|
||||||
position =
|
position =
|
||||||
MeshRenderer::getInstance("testLight")->mTransform.getTranslation();
|
MeshRenderer::getInstance("testLight")->getTransform().getTranslation();
|
||||||
phong->setUniform("uLight.position", position);
|
phong->setUniform("uLight.position", position);
|
||||||
phong->setUniform(
|
phong->setUniform(
|
||||||
"uCameraPosition", ExampleScene::Camera().transform().getTranslation());
|
"uCameraPosition",
|
||||||
posMatrix = phong->mTransform.toMatrix();
|
ExampleScene::getCamera().getTransform().getTranslation());
|
||||||
|
posMatrix = phong->getTransform().toMatrix();
|
||||||
phong->setUniform("uMVP.normalMatrix", posMatrix.normalMatrix());
|
phong->setUniform("uMVP.normalMatrix", posMatrix.normalMatrix());
|
||||||
phong->setUniform("uMVP.model", posMatrix);
|
phong->setUniform("uMVP.model", posMatrix);
|
||||||
phong->setUniform("uMVP.view", ExampleScene::Camera().toMatrix());
|
phong->setUniform("uMVP.view", ExampleScene::getCamera().toMatrix());
|
||||||
phong->setUniform("uMVP.projection", ExampleScene::Projection());
|
phong->setUniform("uMVP.projection", ExampleScene::getProjectionMatrix());
|
||||||
phong->releaseShaders();
|
phong->releaseShaders();
|
||||||
|
|
||||||
// Rotate lighting example cubes
|
// Rotate lighting example cubes
|
||||||
mTestPhong->mTransform.rotate(0.75f, 0.5f, 0.3f, 0.2f);
|
mTestPhong->getTransform().rotate(0.75f, 0.5f, 0.3f, 0.2f);
|
||||||
MeshRenderer::getInstance("noLight")->mTransform.rotate(
|
MeshRenderer::getInstance("noLight")->getTransform().rotate(
|
||||||
0.75f, 0.5f, 0.3f, 0.2f);
|
0.75f, 0.5f, 0.3f, 0.2f);
|
||||||
mTestAmbient->mTransform.rotate(0.75f, 0.5f, 0.3f, 0.2f);
|
mTestAmbient->getTransform().rotate(0.75f, 0.5f, 0.3f, 0.2f);
|
||||||
mTestDiffuse->mTransform.rotate(0.75f, 0.5f, 0.3f, 0.2f);
|
mTestDiffuse->getTransform().rotate(0.75f, 0.5f, 0.3f, 0.2f);
|
||||||
mTestSpecular->mTransform.rotate(0.75f, 0.5f, 0.3f, 0.2f);
|
mTestSpecular->getTransform().rotate(0.75f, 0.5f, 0.3f, 0.2f);
|
||||||
|
|
||||||
// Examples of various translations and rotations
|
// Examples of various translations and rotations
|
||||||
|
|
||||||
// Rotate in multiple directions simultaneously
|
// Rotate in multiple directions simultaneously
|
||||||
MeshRenderer::getInstance("rgbNormalsCube")
|
MeshRenderer::getInstance("rgbNormalsCube")
|
||||||
->mTransform.rotate(0.75f, 0.2f, 0.4f, 0.6f);
|
->getTransform()
|
||||||
|
.rotate(0.75f, 0.2f, 0.4f, 0.6f);
|
||||||
|
|
||||||
// Pitch forward and roll sideways
|
// Pitch forward and roll sideways
|
||||||
MeshRenderer::getInstance("leftTriangle")
|
MeshRenderer::getInstance("leftTriangle")
|
||||||
->mTransform.rotate(0.75f, 1.0f, 0.0f, 0.0f);
|
->getTransform()
|
||||||
|
.rotate(0.75f, 1.0f, 0.0f, 0.0f);
|
||||||
MeshRenderer::getInstance("rightTriangle")
|
MeshRenderer::getInstance("rightTriangle")
|
||||||
->mTransform.rotate(0.75f, 0.0f, 0.0f, 1.0f);
|
->getTransform()
|
||||||
|
.rotate(0.75f, 0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
// Move between two positions over time
|
// Move between two positions over time
|
||||||
static float translateX = 0.025f;
|
static float translateX = 0.025f;
|
||||||
float limit = -9.0f; // Origin position.x - 2.0f
|
float limit = -9.0f; // Origin position.x - 2.0f
|
||||||
float posX =
|
float posX = MeshRenderer::getInstance("topTriangle")
|
||||||
MeshRenderer::getInstance("topTriangle")->mTransform.getTranslation().x();
|
->getTransform()
|
||||||
|
.getTranslation()
|
||||||
|
.x();
|
||||||
if(posX < limit || posX > limit + 4.0f) {
|
if(posX < limit || posX > limit + 4.0f) {
|
||||||
translateX = -translateX;
|
translateX = -translateX;
|
||||||
}
|
}
|
||||||
MeshRenderer::getInstance("topTriangle")
|
MeshRenderer::getInstance("topTriangle")
|
||||||
->mTransform.translate(translateX, 0.0f, 0.0f);
|
->getTransform()
|
||||||
|
.translate(translateX, 0.0f, 0.0f);
|
||||||
MeshRenderer::getInstance("bottomTriangle")
|
MeshRenderer::getInstance("bottomTriangle")
|
||||||
->mTransform.translate(-translateX, 0.0f, 0.0f);
|
->getTransform()
|
||||||
|
.translate(-translateX, 0.0f, 0.0f);
|
||||||
// And lets rotate the triangles in two directions at once
|
// And lets rotate the triangles in two directions at once
|
||||||
MeshRenderer::getInstance("topTriangle")
|
MeshRenderer::getInstance("topTriangle")
|
||||||
->mTransform.rotate(0.75f, 0.2f, 0.0f, 0.4f);
|
->getTransform()
|
||||||
|
.rotate(0.75f, 0.2f, 0.0f, 0.4f);
|
||||||
MeshRenderer::getInstance("bottomTriangle")
|
MeshRenderer::getInstance("bottomTriangle")
|
||||||
->mTransform.rotate(0.75f, 0.0f, 0.2f, 0.4f);
|
->getTransform()
|
||||||
|
.rotate(0.75f, 0.0f, 0.2f, 0.4f);
|
||||||
// And make the bottom triangle green, instead of RGB
|
// And make the bottom triangle green, instead of RGB
|
||||||
|
|
||||||
// Rotate center cube in several directions simultaneously
|
// Rotate center cube in several directions simultaneously
|
||||||
// + Not subject to gimbal lock since we are using quaternions :)
|
// + Not subject to gimbal lock since we are using quaternions :)
|
||||||
MeshRenderer::getInstance("centerCube")
|
MeshRenderer::getInstance("centerCube")
|
||||||
->mTransform.rotate(0.75f, 0.2f, 0.4f, 0.6f);
|
->getTransform()
|
||||||
|
.rotate(0.75f, 0.2f, 0.4f, 0.6f);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,22 +9,65 @@
|
||||||
#ifndef QTK_EXAMPLE_SCENE_H
|
#ifndef QTK_EXAMPLE_SCENE_H
|
||||||
#define QTK_EXAMPLE_SCENE_H
|
#define QTK_EXAMPLE_SCENE_H
|
||||||
|
|
||||||
#include <abstractscene.h>
|
|
||||||
#include <camera3d.h>
|
#include <camera3d.h>
|
||||||
|
#include <scene.h>
|
||||||
#include <skybox.h>
|
#include <skybox.h>
|
||||||
|
|
||||||
#include <QMatrix4x4>
|
#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 {
|
class ExampleScene : public Qtk::Scene {
|
||||||
public:
|
public:
|
||||||
|
/***************************************************************************
|
||||||
|
* Contructors / Destructors
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
ExampleScene();
|
ExampleScene();
|
||||||
~ExampleScene();
|
~ExampleScene();
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* Inherited Public Overrides
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize objects within the scene
|
||||||
|
*/
|
||||||
void init() override;
|
void init() override;
|
||||||
|
/**
|
||||||
|
* Called when OpenGL repaints the widget.
|
||||||
|
*/
|
||||||
void draw() override;
|
void draw() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the Qt `frameSwapped` signal is caught.
|
||||||
|
* See definition of `QtkWidget::initializeGL()`
|
||||||
|
*/
|
||||||
void update() override;
|
void update() override;
|
||||||
|
|
||||||
private:
|
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 * mTestPhong {};
|
||||||
Qtk::MeshRenderer * mTestSpecular {};
|
Qtk::MeshRenderer * mTestSpecular {};
|
||||||
Qtk::MeshRenderer * mTestDiffuse {};
|
Qtk::MeshRenderer * mTestDiffuse {};
|
||||||
|
|
14
app/main.cpp
14
app/main.cpp
|
@ -16,20 +16,6 @@
|
||||||
int main(int argc, char * argv[]) {
|
int main(int argc, char * argv[]) {
|
||||||
QApplication a(argc, 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
|
// Create window for Qt application using custom mainwindow.h
|
||||||
MainWindow w;
|
MainWindow w;
|
||||||
w.show();
|
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 ##
|
||||||
|
## ##
|
||||||
|
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
|
||||||
|
##############################################################################*/
|
||||||
|
|
||||||
#include <mainwindow.h>
|
#include <mainwindow.h>
|
||||||
#include <qtkwidget.h>
|
#include <qtkwidget.h>
|
||||||
#include "ui_mainwindow.h"
|
#include "ui_mainwindow.h"
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget * parent) :
|
MainWindow::MainWindow(QWidget * parent) :
|
||||||
QMainWindow(parent), ui(new Ui::MainWindow) {
|
QMainWindow(parent), ui(new Ui::MainWindow) {
|
||||||
ui->setupUi(this);
|
|
||||||
// For use in design mode using Qt Creator
|
// For use in design mode using Qt Creator
|
||||||
// + We can use the `ui` member to access nested widgets by name
|
// + 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()) {
|
for(const auto widget : ui->qWidget->children()) {
|
||||||
auto qtkWidget = dynamic_cast<Qtk::QtkWidget *>(widget);
|
auto qtkWidget = dynamic_cast<Qtk::QtkWidget *>(widget);
|
||||||
if(qtkWidget != nullptr) {
|
if(qtkWidget != nullptr) {
|
||||||
std::string key = qtkWidget->objectName().toStdString();
|
std::string key = qtkWidget->objectName().toStdString();
|
||||||
|
// Initialize each scene into a map if it doesn't exist.
|
||||||
if(mScenes[key] == nullptr) {
|
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"));
|
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 ##
|
||||||
|
## ##
|
||||||
|
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
|
||||||
|
##############################################################################*/
|
||||||
|
|
||||||
#ifndef MAINWINDOW_H
|
#ifndef MAINWINDOW_H
|
||||||
#define MAINWINDOW_H
|
#define MAINWINDOW_H
|
||||||
|
|
||||||
|
@ -12,16 +20,32 @@ namespace Ui {
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
class QTK_WIDGET_EXPORT MainWindow
|
/**
|
||||||
|
* MainWindow class to provide an example of using a QtkWidget within a Qt
|
||||||
: public QMainWindow {
|
* window application.
|
||||||
|
*/
|
||||||
|
class QTK_WIDGET_EXPORT MainWindow : public QMainWindow {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
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);
|
explicit MainWindow(QWidget * parent = nullptr);
|
||||||
~MainWindow() override;
|
~MainWindow() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/***************************************************************************
|
||||||
|
* Private Members
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
Ui::MainWindow * ui {};
|
Ui::MainWindow * ui {};
|
||||||
std::unordered_map<std::string, Qtk::Scene *> mScenes {};
|
std::unordered_map<std::string, Qtk::Scene *> mScenes {};
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,6 +13,19 @@
|
||||||
#ifndef QTK_RESOURCEMANAGER_H
|
#ifndef QTK_RESOURCEMANAGER_H
|
||||||
#define 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 {
|
typedef class ResourceManager {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
@ -24,7 +37,7 @@ typedef class ResourceManager {
|
||||||
* ':/models/backpack/backpack.obj' An asset at location
|
* ':/models/backpack/backpack.obj' An asset at location
|
||||||
* qtk/resources/path/to/asset.obj Should be given in qrc format:
|
* qtk/resources/path/to/asset.obj Should be given in qrc format:
|
||||||
* ':/path/to/asset.obj'
|
* ':/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) {
|
static std::string getPath(const std::string & path) {
|
||||||
// Only construct qtk resource path if in qrc format; else return it as-is
|
// Only construct qtk resource path if in qrc format; else return it as-is
|
||||||
|
|
|
@ -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) {
|
QDataStream & operator<<(QDataStream & out, Camera3D & transform) {
|
||||||
out << transform.transform();
|
out << transform.getTransform();
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDataStream & operator>>(QDataStream & in, Camera3D & transform) {
|
QDataStream & operator>>(QDataStream & in, Camera3D & transform) {
|
||||||
in >> transform.transform();
|
in >> transform.getTransform();
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDebug operator<<(QDebug dbg, const Camera3D & transform) {
|
QDebug operator<<(QDebug dbg, const Camera3D & transform) {
|
||||||
dbg << "Camera3D\n{\n";
|
dbg << "Camera3D\n{\n";
|
||||||
dbg << "Position: <" << transform.translation().x() << ", "
|
dbg << "Position: <" << transform.getTranslation().x() << ", "
|
||||||
<< transform.translation().y() << ", " << transform.translation().z()
|
<< transform.getTranslation().y() << ", "
|
||||||
<< ">\n";
|
<< transform.getTranslation().z() << ">\n";
|
||||||
dbg << "Rotation: <" << transform.rotation().x() << ", "
|
dbg << "Rotation: <" << transform.getRotation().x() << ", "
|
||||||
<< transform.rotation().y() << ", " << transform.rotation().z() << " | "
|
<< transform.getRotation().y() << ", " << transform.getRotation().z()
|
||||||
<< transform.rotation().scalar() << ">\n}";
|
<< " | " << transform.getRotation().scalar() << ">\n}";
|
||||||
return dbg;
|
return dbg;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,19 +17,25 @@
|
||||||
namespace Qtk {
|
namespace Qtk {
|
||||||
class QTKAPI Camera3D {
|
class QTKAPI Camera3D {
|
||||||
public:
|
public:
|
||||||
// Constants
|
/*************************************************************************
|
||||||
|
* Constants
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
static const QVector3D LocalForward;
|
static const QVector3D LocalForward;
|
||||||
static const QVector3D LocalUp;
|
static const QVector3D LocalUp;
|
||||||
static const QVector3D LocalRight;
|
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();
|
return mTransform.getTranslation();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline const QQuaternion & rotation() const {
|
[[nodiscard]] inline const QQuaternion & getRotation() const {
|
||||||
return mTransform.getRotation();
|
return mTransform.getRotation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,9 +55,17 @@ namespace Qtk {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/*************************************************************************
|
||||||
|
* Private Members
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
Transform3D mTransform;
|
Transform3D mTransform;
|
||||||
QMatrix4x4 mWorld;
|
QMatrix4x4 mWorld;
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Private Methods
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
#ifndef QT_NO_DATASTREAM
|
#ifndef QT_NO_DATASTREAM
|
||||||
friend QDataStream & operator<<(QDataStream & out, Camera3D & transform);
|
friend QDataStream & operator<<(QDataStream & out, Camera3D & transform);
|
||||||
friend QDataStream & operator>>(QDataStream & in, Camera3D & transform);
|
friend QDataStream & operator>>(QDataStream & in, Camera3D & transform);
|
||||||
|
|
17
src/input.h
17
src/input.h
|
@ -17,10 +17,15 @@
|
||||||
|
|
||||||
namespace Qtk {
|
namespace Qtk {
|
||||||
class QTKAPI Input {
|
class QTKAPI Input {
|
||||||
|
public:
|
||||||
|
/*************************************************************************
|
||||||
|
* Typedefs
|
||||||
|
************************************************************************/
|
||||||
friend class Qtk::QtkWidget;
|
friend class Qtk::QtkWidget;
|
||||||
|
|
||||||
public:
|
/**
|
||||||
// Possible key states
|
* Possible key states
|
||||||
|
*/
|
||||||
enum InputState {
|
enum InputState {
|
||||||
InputInvalid,
|
InputInvalid,
|
||||||
InputRegistered,
|
InputRegistered,
|
||||||
|
@ -30,6 +35,10 @@ namespace Qtk {
|
||||||
InputReleased
|
InputReleased
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Public Methods
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
// State checking
|
// State checking
|
||||||
inline static bool keyTriggered(Qt::Key key) {
|
inline static bool keyTriggered(Qt::Key key) {
|
||||||
return keyState(key) == InputTriggered;
|
return keyState(key) == InputTriggered;
|
||||||
|
@ -63,6 +72,10 @@ namespace Qtk {
|
||||||
static QPoint mouseDelta();
|
static QPoint mouseDelta();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/*************************************************************************
|
||||||
|
* Private Methods
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
// State updating
|
// State updating
|
||||||
static void update();
|
static void update();
|
||||||
static void registerKeyPress(int key);
|
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
|
|
254
src/mesh.cpp
254
src/mesh.cpp
|
@ -13,6 +13,9 @@ using namespace Qtk;
|
||||||
Cube::Cube(DrawMode mode) {
|
Cube::Cube(DrawMode mode) {
|
||||||
mDrawMode = mode;
|
mDrawMode = mode;
|
||||||
switch(mode) {
|
switch(mode) {
|
||||||
|
// The order of the following assignment values helps to visualize.
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
// Cube data for use with glDrawArrays
|
// Cube data for use with glDrawArrays
|
||||||
case QTK_DRAW_ARRAYS:
|
case QTK_DRAW_ARRAYS:
|
||||||
mIndices = {/* No indices needed for glDrawArrays */};
|
mIndices = {/* No indices needed for glDrawArrays */};
|
||||||
|
@ -20,51 +23,76 @@ Cube::Cube(DrawMode mode) {
|
||||||
mNormals = {FACE_FRONT, FACE_BACK, FACE_TOP,
|
mNormals = {FACE_FRONT, FACE_BACK, FACE_TOP,
|
||||||
FACE_BOTTOM, FACE_LEFT, FACE_RIGHT};
|
FACE_BOTTOM, FACE_LEFT, FACE_RIGHT};
|
||||||
|
|
||||||
mVertices = {// Face 1 (Front)
|
// We're drawing triangles to construct the geometry of a cube.
|
||||||
VERTEX_FTR, VERTEX_FTL, VERTEX_FBL, VERTEX_FBL, VERTEX_FBR,
|
// Each triangle is made up of three points.
|
||||||
VERTEX_FTR,
|
// The entire cube has 12 triangles to make 6 square faces of the cube.
|
||||||
|
mVertices = {
|
||||||
|
// Face 1 (Front)
|
||||||
|
VERTEX_FTR, VERTEX_FTL, VERTEX_FBL,
|
||||||
|
VERTEX_FBL, VERTEX_FBR, VERTEX_FTR,
|
||||||
// Face 2 (Back)
|
// Face 2 (Back)
|
||||||
VERTEX_BBR, VERTEX_BTL, VERTEX_BTR, VERTEX_BTL, VERTEX_BBR,
|
VERTEX_BBR, VERTEX_BTL, VERTEX_BTR,
|
||||||
VERTEX_BBL,
|
VERTEX_BTL, VERTEX_BBR, VERTEX_BBL,
|
||||||
// Face 3 (Top)
|
// Face 3 (Top)
|
||||||
VERTEX_FTR, VERTEX_BTR, VERTEX_BTL, VERTEX_BTL, VERTEX_FTL,
|
VERTEX_FTR, VERTEX_BTR, VERTEX_BTL,
|
||||||
VERTEX_FTR,
|
VERTEX_BTL, VERTEX_FTL, VERTEX_FTR,
|
||||||
// Face 4 (Bottom)
|
// Face 4 (Bottom)
|
||||||
VERTEX_FBR, VERTEX_FBL, VERTEX_BBL, VERTEX_BBL, VERTEX_BBR,
|
VERTEX_FBR, VERTEX_FBL, VERTEX_BBL,
|
||||||
VERTEX_FBR,
|
VERTEX_BBL, VERTEX_BBR, VERTEX_FBR,
|
||||||
// Face 5 (Left)
|
// Face 5 (Left)
|
||||||
VERTEX_FBL, VERTEX_FTL, VERTEX_BTL, VERTEX_FBL, VERTEX_BTL,
|
VERTEX_FBL, VERTEX_FTL, VERTEX_BTL,
|
||||||
VERTEX_BBL,
|
VERTEX_FBL, VERTEX_BTL, VERTEX_BBL,
|
||||||
// Face 6 (Right)
|
// Face 6 (Right)
|
||||||
VERTEX_FTR, VERTEX_FBR, VERTEX_BBR, VERTEX_BBR, VERTEX_BTR,
|
VERTEX_FTR, VERTEX_FBR, VERTEX_BBR,
|
||||||
VERTEX_FTR};
|
VERTEX_BBR, VERTEX_BTR, VERTEX_FTR
|
||||||
|
};
|
||||||
|
|
||||||
mColors = {// Face 1 (Front)
|
// Setting colors for each vertex that we defined above.
|
||||||
RED, GREEN, BLUE, BLUE, WHITE, RED,
|
// These are defaults and can be overriden by the caller with setColor().
|
||||||
|
// The colors below are interpolated from vertex to vertex.
|
||||||
|
mColors = {
|
||||||
|
// Face 1 (Front)
|
||||||
|
RED, GREEN, BLUE,
|
||||||
|
BLUE, WHITE, RED,
|
||||||
// Face 2 (Back)
|
// Face 2 (Back)
|
||||||
YELLOW, CYAN, MAGENTA, CYAN, YELLOW, BLACK,
|
YELLOW, CYAN, MAGENTA,
|
||||||
|
CYAN, YELLOW, BLACK,
|
||||||
// Face 3 (Top)
|
// Face 3 (Top)
|
||||||
RED, MAGENTA, CYAN, CYAN, GREEN, RED,
|
RED, MAGENTA, CYAN,
|
||||||
|
CYAN, GREEN, RED,
|
||||||
// Face 4 (Bottom)
|
// Face 4 (Bottom)
|
||||||
WHITE, BLUE, BLACK, BLACK, YELLOW, WHITE,
|
WHITE, BLUE, BLACK,
|
||||||
|
BLACK, YELLOW, WHITE,
|
||||||
// Face 5 (Left)
|
// Face 5 (Left)
|
||||||
BLUE, GREEN, CYAN, BLUE, CYAN, BLACK,
|
BLUE, GREEN, CYAN,
|
||||||
|
BLUE, CYAN, BLACK,
|
||||||
// Face 6 (Right)
|
// Face 6 (Right)
|
||||||
RED, WHITE, YELLOW, YELLOW, MAGENTA, RED};
|
RED, WHITE, YELLOW,
|
||||||
|
YELLOW, MAGENTA, RED
|
||||||
|
};
|
||||||
|
|
||||||
mTexCoords = {// Face 1 (Front)
|
// Define texture coordinates for the cube.
|
||||||
UV_TOP, UV_ORIGIN, UV_RIGHT, UV_RIGHT, UV_CORNER, UV_TOP,
|
// This defines the orientation of the texture when applied the object.
|
||||||
|
mTexCoords = {
|
||||||
|
// Face 1 (Front)
|
||||||
|
UV_TOP, UV_ORIGIN, UV_RIGHT,
|
||||||
|
UV_RIGHT, UV_CORNER, UV_TOP,
|
||||||
// Face 2 (Back)
|
// Face 2 (Back)
|
||||||
UV_TOP, UV_RIGHT, UV_CORNER, UV_RIGHT, UV_TOP, UV_ORIGIN,
|
UV_TOP, UV_RIGHT, UV_CORNER,
|
||||||
|
UV_RIGHT, UV_TOP, UV_ORIGIN,
|
||||||
// Face 3 (Top)
|
// Face 3 (Top)
|
||||||
UV_CORNER, UV_TOP, UV_ORIGIN, UV_ORIGIN, UV_RIGHT,
|
UV_CORNER, UV_TOP, UV_ORIGIN,
|
||||||
UV_CORNER,
|
UV_ORIGIN, UV_RIGHT, UV_CORNER,
|
||||||
// Face 4 (Bottom)
|
// Face 4 (Bottom)
|
||||||
UV_TOP, UV_ORIGIN, UV_RIGHT, UV_RIGHT, UV_CORNER, UV_TOP,
|
UV_TOP, UV_ORIGIN, UV_RIGHT,
|
||||||
|
UV_RIGHT, UV_CORNER, UV_TOP,
|
||||||
// Face 5 (Left)
|
// Face 5 (Left)
|
||||||
UV_TOP, UV_CORNER, UV_RIGHT, UV_TOP, UV_RIGHT, UV_ORIGIN,
|
UV_TOP, UV_CORNER, UV_RIGHT,
|
||||||
|
UV_TOP, UV_RIGHT, UV_ORIGIN,
|
||||||
// Face 6 (Right)
|
// Face 6 (Right)
|
||||||
UV_TOP, UV_CORNER, UV_RIGHT, UV_RIGHT, UV_ORIGIN, UV_TOP};
|
UV_TOP, UV_CORNER, UV_RIGHT,
|
||||||
|
UV_RIGHT, UV_ORIGIN, UV_TOP
|
||||||
|
};
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -81,7 +109,9 @@ Cube::Cube(DrawMode mode) {
|
||||||
VERTEX_FTR, VERTEX_FTL, VERTEX_FBL, VERTEX_FBR,
|
VERTEX_FTR, VERTEX_FTL, VERTEX_FBL, VERTEX_FBR,
|
||||||
// 4 5 6 7
|
// 4 5 6 7
|
||||||
VERTEX_BTR, VERTEX_BTL, VERTEX_BBL, VERTEX_BBR};
|
VERTEX_BTR, VERTEX_BTL, VERTEX_BBL, VERTEX_BBR};
|
||||||
mIndices = {// Face 1 (Front)
|
|
||||||
|
mIndices = {
|
||||||
|
// Face 1 (Front)
|
||||||
0, 1, 2, 2, 3, 0,
|
0, 1, 2, 2, 3, 0,
|
||||||
// Face 2 (Back)
|
// Face 2 (Back)
|
||||||
7, 5, 4, 5, 7, 6,
|
7, 5, 4, 5, 7, 6,
|
||||||
|
@ -92,14 +122,17 @@ Cube::Cube(DrawMode mode) {
|
||||||
// Face 5 (Left)
|
// Face 5 (Left)
|
||||||
2, 1, 5, 2, 5, 6,
|
2, 1, 5, 2, 5, 6,
|
||||||
// Face 6 (Right)
|
// Face 6 (Right)
|
||||||
0, 3, 7, 7, 4, 0};
|
0, 3, 7, 7, 4, 0
|
||||||
|
};
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Cube shape data for using normals and UVs with glDrawElements
|
// Cube shape data for using normals and UVs with glDrawElements
|
||||||
case QTK_DRAW_ELEMENTS_NORMALS:
|
case QTK_DRAW_ELEMENTS_NORMALS:
|
||||||
mColors = {RED, GREEN, BLUE, WHITE, YELLOW, CYAN, MAGENTA, BLACK};
|
mColors = {RED, GREEN, BLUE, WHITE, YELLOW, CYAN, MAGENTA, BLACK};
|
||||||
|
|
||||||
mVertices = {// Face 1 (Front)
|
mVertices = {
|
||||||
|
// Face 1 (Front)
|
||||||
// 0 1 2 3
|
// 0 1 2 3
|
||||||
VERTEX_FTL, VERTEX_FBL, VERTEX_FBR, VERTEX_FTR,
|
VERTEX_FTL, VERTEX_FBL, VERTEX_FBR, VERTEX_FTR,
|
||||||
// Face 2 (Back)
|
// Face 2 (Back)
|
||||||
|
@ -116,9 +149,11 @@ Cube::Cube(DrawMode mode) {
|
||||||
VERTEX_FBL, VERTEX_BBL, VERTEX_BTL, VERTEX_FTL,
|
VERTEX_FBL, VERTEX_BBL, VERTEX_BTL, VERTEX_FTL,
|
||||||
// Face 6 (Right)
|
// Face 6 (Right)
|
||||||
// 20 21 22 23
|
// 20 21 22 23
|
||||||
VERTEX_FBR, VERTEX_BBR, VERTEX_BTR, VERTEX_FTR};
|
VERTEX_FBR, VERTEX_BBR, VERTEX_BTR, VERTEX_FTR
|
||||||
|
};
|
||||||
|
|
||||||
mIndices = {// Face 1 (Front)
|
mIndices = {
|
||||||
|
// Face 1 (Front)
|
||||||
0, 1, 2, 2, 3, 0,
|
0, 1, 2, 2, 3, 0,
|
||||||
// Face 2 (Back)
|
// Face 2 (Back)
|
||||||
4, 5, 6, 6, 7, 4,
|
4, 5, 6, 6, 7, 4,
|
||||||
|
@ -126,11 +161,12 @@ Cube::Cube(DrawMode mode) {
|
||||||
8, 9, 10, 10, 11, 8,
|
8, 9, 10, 10, 11, 8,
|
||||||
// Face 4 (Bottom)
|
// Face 4 (Bottom)
|
||||||
12, 13, 14, 14, 15, 12,
|
12, 13, 14, 14, 15, 12,
|
||||||
|
|
||||||
// Face 5 (Left)
|
// Face 5 (Left)
|
||||||
16, 17, 18, 18, 19, 16,
|
16, 17, 18, 18, 19, 16,
|
||||||
// Face 6 (Right)
|
// Face 6 (Right)
|
||||||
20, 21, 22, 22, 23, 20};
|
20, 21, 22, 22, 23, 20
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
mNormals = {
|
mNormals = {
|
||||||
VECTOR_FORWARD, VECTOR_FORWARD, VECTOR_FORWARD, VECTOR_FORWARD,
|
VECTOR_FORWARD, VECTOR_FORWARD, VECTOR_FORWARD, VECTOR_FORWARD,
|
||||||
|
@ -143,50 +179,27 @@ Cube::Cube(DrawMode mode) {
|
||||||
|
|
||||||
mTexCoords = {
|
mTexCoords = {
|
||||||
// Face 1 (Front)
|
// Face 1 (Front)
|
||||||
UV_TOP,
|
UV_TOP, UV_RIGHT, UV_CORNER,
|
||||||
UV_RIGHT,
|
UV_RIGHT, UV_TOP, UV_ORIGIN,
|
||||||
UV_CORNER,
|
|
||||||
UV_RIGHT,
|
|
||||||
UV_TOP,
|
|
||||||
UV_ORIGIN,
|
|
||||||
// Face 2 (Back)
|
// Face 2 (Back)
|
||||||
UV_TOP,
|
UV_TOP, UV_RIGHT, UV_CORNER,
|
||||||
UV_RIGHT,
|
UV_RIGHT, UV_TOP, UV_ORIGIN,
|
||||||
UV_CORNER,
|
|
||||||
UV_RIGHT,
|
|
||||||
UV_TOP,
|
|
||||||
UV_ORIGIN,
|
|
||||||
// Face 3 (Top)
|
// Face 3 (Top)
|
||||||
UV_TOP,
|
UV_TOP, UV_RIGHT, UV_CORNER,
|
||||||
UV_RIGHT,
|
UV_RIGHT, UV_TOP, UV_ORIGIN,
|
||||||
UV_CORNER,
|
|
||||||
UV_RIGHT,
|
|
||||||
UV_TOP,
|
|
||||||
UV_ORIGIN,
|
|
||||||
// Face 4 (Bottom)
|
// Face 4 (Bottom)
|
||||||
UV_TOP,
|
UV_TOP, UV_RIGHT, UV_CORNER,
|
||||||
UV_RIGHT,
|
UV_RIGHT, UV_TOP, UV_ORIGIN,
|
||||||
UV_CORNER,
|
|
||||||
UV_RIGHT,
|
|
||||||
UV_TOP,
|
|
||||||
UV_ORIGIN,
|
|
||||||
// Face 5 (Left)
|
// Face 5 (Left)
|
||||||
UV_TOP,
|
UV_TOP, UV_RIGHT, UV_CORNER,
|
||||||
UV_RIGHT,
|
UV_RIGHT, UV_TOP, UV_ORIGIN,
|
||||||
UV_CORNER,
|
|
||||||
UV_RIGHT,
|
|
||||||
UV_TOP,
|
|
||||||
UV_ORIGIN,
|
|
||||||
// Face 6 (Right)
|
// Face 6 (Right)
|
||||||
UV_TOP,
|
UV_TOP, UV_RIGHT, UV_CORNER,
|
||||||
UV_RIGHT,
|
UV_RIGHT, UV_TOP, UV_ORIGIN,
|
||||||
UV_CORNER,
|
|
||||||
UV_RIGHT,
|
|
||||||
UV_TOP,
|
|
||||||
UV_ORIGIN,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
// clang-format on
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,6 +207,8 @@ Triangle::Triangle(DrawMode mode) {
|
||||||
mDrawMode = mode;
|
mDrawMode = mode;
|
||||||
const QVector3D triangleTop = QVector3D(0.0f, 0.5f, 0.0f);
|
const QVector3D triangleTop = QVector3D(0.0f, 0.5f, 0.0f);
|
||||||
switch(mode) {
|
switch(mode) {
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
case QTK_DRAW_ARRAYS:
|
case QTK_DRAW_ARRAYS:
|
||||||
mIndices = {/* No indices needed for glDrawArrays */};
|
mIndices = {/* No indices needed for glDrawArrays */};
|
||||||
|
|
||||||
|
@ -201,29 +216,17 @@ Triangle::Triangle(DrawMode mode) {
|
||||||
|
|
||||||
mVertices = {
|
mVertices = {
|
||||||
// Bottom face (Base of the pyramid)
|
// Bottom face (Base of the pyramid)
|
||||||
VERTEX_BBL,
|
VERTEX_BBL, VERTEX_BBR, VERTEX_FBR,
|
||||||
VERTEX_BBR,
|
VERTEX_FBR, VERTEX_FBL, VERTEX_BBL,
|
||||||
VERTEX_FBR,
|
|
||||||
VERTEX_FBR,
|
|
||||||
VERTEX_FBL,
|
|
||||||
VERTEX_BBL,
|
|
||||||
|
|
||||||
// Front face
|
// Front face
|
||||||
VERTEX_FBL,
|
VERTEX_FBL, VERTEX_FBR, triangleTop,
|
||||||
VERTEX_FBR,
|
|
||||||
triangleTop,
|
|
||||||
// Back face
|
// Back face
|
||||||
VERTEX_BBR,
|
VERTEX_BBR, VERTEX_BBL, triangleTop,
|
||||||
VERTEX_BBL,
|
|
||||||
triangleTop,
|
|
||||||
// Left face
|
// Left face
|
||||||
VERTEX_BBL,
|
VERTEX_BBL, VERTEX_FBL, triangleTop,
|
||||||
VERTEX_FBL,
|
|
||||||
triangleTop,
|
|
||||||
// Right face
|
// Right face
|
||||||
VERTEX_FBR,
|
VERTEX_FBR, VERTEX_BBR, triangleTop,
|
||||||
VERTEX_BBR,
|
|
||||||
triangleTop,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Find normals for each triangle of the mesh
|
// Find normals for each triangle of the mesh
|
||||||
|
@ -238,29 +241,17 @@ Triangle::Triangle(DrawMode mode) {
|
||||||
|
|
||||||
mTexCoords = {
|
mTexCoords = {
|
||||||
// Bottom face (Base of the pyramid)
|
// Bottom face (Base of the pyramid)
|
||||||
UV_ORIGIN,
|
UV_ORIGIN, UV_RIGHT, UV_CORNER,
|
||||||
UV_RIGHT,
|
UV_CORNER, UV_TOP, UV_ORIGIN,
|
||||||
UV_CORNER,
|
|
||||||
UV_CORNER,
|
|
||||||
UV_TOP,
|
|
||||||
UV_ORIGIN,
|
|
||||||
|
|
||||||
// Front face
|
// Front face
|
||||||
UV_ORIGIN,
|
UV_ORIGIN, UV_RIGHT, UV_CORNER,
|
||||||
UV_RIGHT,
|
|
||||||
UV_CORNER,
|
|
||||||
// Back face
|
// Back face
|
||||||
UV_ORIGIN,
|
UV_ORIGIN, UV_RIGHT, UV_CORNER,
|
||||||
UV_RIGHT,
|
|
||||||
UV_CORNER,
|
|
||||||
// Left face
|
// Left face
|
||||||
UV_ORIGIN,
|
UV_ORIGIN, UV_RIGHT, UV_CORNER,
|
||||||
UV_RIGHT,
|
|
||||||
UV_CORNER,
|
|
||||||
// Right face
|
// Right face
|
||||||
UV_ORIGIN,
|
UV_ORIGIN, UV_RIGHT, UV_CORNER,
|
||||||
UV_RIGHT,
|
|
||||||
UV_CORNER,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -296,34 +287,22 @@ Triangle::Triangle(DrawMode mode) {
|
||||||
mVertices = {
|
mVertices = {
|
||||||
// Bottom face
|
// Bottom face
|
||||||
// 0 1 2
|
// 0 1 2
|
||||||
VERTEX_FBL,
|
VERTEX_FBL, VERTEX_FBR, VERTEX_BBL,
|
||||||
VERTEX_FBR,
|
|
||||||
VERTEX_BBL,
|
|
||||||
// 3 4 5
|
// 3 4 5
|
||||||
VERTEX_BBR,
|
VERTEX_BBR, VERTEX_FBR, VERTEX_BBL,
|
||||||
VERTEX_FBR,
|
|
||||||
VERTEX_BBL,
|
|
||||||
|
|
||||||
// Front face
|
// Front face
|
||||||
// 6 7 8
|
// 6 7 8
|
||||||
VERTEX_FBL,
|
VERTEX_FBL, VERTEX_FBR, triangleTop,
|
||||||
VERTEX_FBR,
|
|
||||||
triangleTop,
|
|
||||||
// Back face
|
// Back face
|
||||||
// 9 10 11
|
// 9 10 11
|
||||||
VERTEX_BBR,
|
VERTEX_BBR, VERTEX_BBL, triangleTop,
|
||||||
VERTEX_BBL,
|
|
||||||
triangleTop,
|
|
||||||
// Left face
|
// Left face
|
||||||
// 12 13 14
|
// 12 13 14
|
||||||
VERTEX_BBL,
|
VERTEX_BBL, VERTEX_FBL, triangleTop,
|
||||||
VERTEX_FBL,
|
|
||||||
triangleTop,
|
|
||||||
// Right face
|
// Right face
|
||||||
// 15 16 17
|
// 15 16 17
|
||||||
VERTEX_FBR,
|
VERTEX_FBR, VERTEX_BBR, triangleTop,
|
||||||
VERTEX_BBR,
|
|
||||||
triangleTop,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
mIndices = {
|
mIndices = {
|
||||||
|
@ -350,30 +329,19 @@ Triangle::Triangle(DrawMode mode) {
|
||||||
|
|
||||||
mTexCoords = {
|
mTexCoords = {
|
||||||
// Bottom face
|
// Bottom face
|
||||||
UV_ORIGIN,
|
UV_ORIGIN, UV_RIGHT, UV_TOP,
|
||||||
UV_RIGHT,
|
UV_CORNER, UV_RIGHT, UV_TOP,
|
||||||
UV_TOP,
|
|
||||||
UV_CORNER,
|
|
||||||
UV_RIGHT,
|
|
||||||
UV_TOP,
|
|
||||||
|
|
||||||
// Front face
|
// Front face
|
||||||
UV_ORIGIN,
|
UV_ORIGIN, UV_RIGHT, UV_CORNER,
|
||||||
UV_RIGHT,
|
|
||||||
UV_CORNER,
|
|
||||||
// Back face
|
// Back face
|
||||||
UV_ORIGIN,
|
UV_ORIGIN, UV_RIGHT, UV_CORNER,
|
||||||
UV_RIGHT,
|
|
||||||
UV_CORNER,
|
|
||||||
// Left face
|
// Left face
|
||||||
UV_ORIGIN,
|
UV_ORIGIN, UV_RIGHT, UV_CORNER,
|
||||||
UV_RIGHT,
|
|
||||||
UV_CORNER,
|
|
||||||
// Right face
|
// Right face
|
||||||
UV_ORIGIN,
|
UV_ORIGIN, UV_RIGHT, UV_CORNER,
|
||||||
UV_RIGHT,
|
|
||||||
UV_CORNER,
|
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
// clang-format on
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
67
src/mesh.h
67
src/mesh.h
|
@ -46,21 +46,22 @@ namespace Qtk {
|
||||||
#define VECTOR_ONE QVector3D(1.0f, 1.0f, 1.0f)
|
#define VECTOR_ONE QVector3D(1.0f, 1.0f, 1.0f)
|
||||||
#define VECTOR_ZERO QVector3D(0.0f, 0.0f, 0.0f)
|
#define VECTOR_ZERO QVector3D(0.0f, 0.0f, 0.0f)
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
// A series of direction vectors to represent cube face normal
|
// A series of direction vectors to represent cube face normal
|
||||||
#define FACE_TOP \
|
#define FACE_TOP VECTOR_UP, VECTOR_UP, VECTOR_UP, \
|
||||||
VECTOR_UP, VECTOR_UP, VECTOR_UP, VECTOR_UP, VECTOR_UP, VECTOR_UP
|
VECTOR_UP, VECTOR_UP, VECTOR_UP
|
||||||
#define FACE_BOTTOM \
|
#define FACE_BOTTOM VECTOR_DOWN, VECTOR_DOWN, VECTOR_DOWN, \
|
||||||
VECTOR_DOWN, VECTOR_DOWN, VECTOR_DOWN, VECTOR_DOWN, VECTOR_DOWN, VECTOR_DOWN
|
VECTOR_DOWN, VECTOR_DOWN, VECTOR_DOWN
|
||||||
#define FACE_LEFT \
|
#define FACE_LEFT VECTOR_LEFT, VECTOR_LEFT, VECTOR_LEFT, \
|
||||||
VECTOR_LEFT, VECTOR_LEFT, VECTOR_LEFT, VECTOR_LEFT, VECTOR_LEFT, VECTOR_LEFT
|
VECTOR_LEFT, VECTOR_LEFT, VECTOR_LEFT
|
||||||
#define FACE_RIGHT \
|
#define FACE_RIGHT VECTOR_RIGHT, VECTOR_RIGHT, VECTOR_RIGHT, \
|
||||||
VECTOR_RIGHT, VECTOR_RIGHT, VECTOR_RIGHT, VECTOR_RIGHT, VECTOR_RIGHT, \
|
VECTOR_RIGHT, VECTOR_RIGHT, VECTOR_RIGHT
|
||||||
VECTOR_RIGHT
|
#define FACE_FRONT VECTOR_FORWARD, VECTOR_FORWARD, VECTOR_FORWARD, \
|
||||||
#define FACE_FRONT \
|
VECTOR_FORWARD, VECTOR_FORWARD, VECTOR_FORWARD
|
||||||
VECTOR_FORWARD, VECTOR_FORWARD, VECTOR_FORWARD, VECTOR_FORWARD, \
|
#define FACE_BACK VECTOR_BACK, VECTOR_BACK, VECTOR_BACK, \
|
||||||
VECTOR_FORWARD, VECTOR_FORWARD
|
VECTOR_BACK, VECTOR_BACK, VECTOR_BACK
|
||||||
#define FACE_BACK \
|
// clang-format on
|
||||||
VECTOR_BACK, VECTOR_BACK, VECTOR_BACK, VECTOR_BACK, VECTOR_BACK, VECTOR_BACK
|
|
||||||
|
|
||||||
// Colors using QVector3Ds as RGB values
|
// Colors using QVector3Ds as RGB values
|
||||||
#define WHITE VECTOR_ONE
|
#define WHITE VECTOR_ONE
|
||||||
|
@ -84,13 +85,26 @@ namespace Qtk {
|
||||||
typedef std::vector<QVector2D> TexCoords;
|
typedef std::vector<QVector2D> TexCoords;
|
||||||
typedef std::vector<QVector3D> Normals;
|
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 {
|
enum DrawMode {
|
||||||
QTK_DRAW_ARRAYS,
|
QTK_DRAW_ARRAYS,
|
||||||
QTK_DRAW_ELEMENTS,
|
QTK_DRAW_ELEMENTS,
|
||||||
QTK_DRAW_ELEMENTS_NORMALS
|
QTK_DRAW_ELEMENTS_NORMALS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for all simple shape objects.
|
||||||
|
*/
|
||||||
struct QTKAPI ShapeBase {
|
struct QTKAPI ShapeBase {
|
||||||
|
public:
|
||||||
|
/*************************************************************************
|
||||||
|
* Constructors / Destructors
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
explicit ShapeBase(
|
explicit ShapeBase(
|
||||||
DrawMode mode = QTK_DRAW_ARRAYS, Vertices v = {}, Indices i = {},
|
DrawMode mode = QTK_DRAW_ARRAYS, Vertices v = {}, Indices i = {},
|
||||||
Colors c = {}, TexCoords t = {}, Normals n = {}) :
|
Colors c = {}, TexCoords t = {}, Normals n = {}) :
|
||||||
|
@ -99,6 +113,10 @@ namespace Qtk {
|
||||||
mIndices(std::move(i)), mTexCoords(std::move(t)),
|
mIndices(std::move(i)), mTexCoords(std::move(t)),
|
||||||
mNormals(std::move(n)) {}
|
mNormals(std::move(n)) {}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Accessors
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
[[nodiscard]] inline const Vertices & getVertices() const {
|
[[nodiscard]] inline const Vertices & getVertices() const {
|
||||||
return mVertices;
|
return mVertices;
|
||||||
}
|
}
|
||||||
|
@ -122,6 +140,10 @@ namespace Qtk {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
/*************************************************************************
|
||||||
|
* Protected Members
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
DrawMode mDrawMode;
|
DrawMode mDrawMode;
|
||||||
|
|
||||||
Vertices mVertices {};
|
Vertices mVertices {};
|
||||||
|
@ -132,13 +154,26 @@ namespace Qtk {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Shape : public ShapeBase {
|
struct Shape : public ShapeBase {
|
||||||
|
public:
|
||||||
|
/*************************************************************************
|
||||||
|
* Typedefs
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
friend MeshRenderer;
|
friend MeshRenderer;
|
||||||
friend Object;
|
friend Object;
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Constructors / Destructors
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
Shape() = default;
|
Shape() = default;
|
||||||
|
|
||||||
explicit Shape(const ShapeBase & rhs) : ShapeBase(rhs) {}
|
explicit Shape(const ShapeBase & rhs) : ShapeBase(rhs) {}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Setters
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
virtual inline void setVertices(const Vertices & value) {
|
virtual inline void setVertices(const Vertices & value) {
|
||||||
mVertices = value;
|
mVertices = value;
|
||||||
}
|
}
|
||||||
|
@ -160,13 +195,15 @@ namespace Qtk {
|
||||||
virtual inline void setShape(const Shape & value) { *this = value; }
|
virtual inline void setShape(const Shape & value) { *this = value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Primitives inherit from ShapeBase, does not allow setting of shape values
|
/* Primitives inherit from ShapeBase, doesn't allow setting shape values. */
|
||||||
class QTKAPI Mesh {};
|
class QTKAPI Mesh {};
|
||||||
|
|
||||||
|
/* Simple Cube shape. */
|
||||||
struct QTKAPI Cube : public ShapeBase {
|
struct QTKAPI Cube : public ShapeBase {
|
||||||
explicit Cube(DrawMode mode = QTK_DRAW_ARRAYS);
|
explicit Cube(DrawMode mode = QTK_DRAW_ARRAYS);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Simple Triangle shape. */
|
||||||
struct QTKAPI Triangle : public ShapeBase {
|
struct QTKAPI Triangle : public ShapeBase {
|
||||||
explicit Triangle(DrawMode mode = QTK_DRAW_ARRAYS);
|
explicit Triangle(DrawMode mode = QTK_DRAW_ARRAYS);
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
|
|
||||||
#include <QImageReader>
|
#include <QImageReader>
|
||||||
|
|
||||||
#include <abstractscene.h>
|
|
||||||
#include <meshrenderer.h>
|
#include <meshrenderer.h>
|
||||||
|
#include <scene.h>
|
||||||
#include <texture.h>
|
#include <texture.h>
|
||||||
|
|
||||||
using namespace Qtk;
|
using namespace Qtk;
|
||||||
|
@ -31,6 +31,13 @@ MeshRenderer::~MeshRenderer() {
|
||||||
|
|
||||||
// Static member function to retrieve instances of MeshRenderers
|
// Static member function to retrieve instances of MeshRenderers
|
||||||
MeshRenderer * MeshRenderer::getInstance(const QString & name) {
|
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];
|
return sInstances[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,8 +133,8 @@ void MeshRenderer::setShaders(
|
||||||
void MeshRenderer::setUniformMVP(
|
void MeshRenderer::setUniformMVP(
|
||||||
const char * model, const char * view, const char * projection) {
|
const char * model, const char * view, const char * projection) {
|
||||||
ShaderBindScope lock(&mProgram, mBound);
|
ShaderBindScope lock(&mProgram, mBound);
|
||||||
mProgram.setUniformValue(projection, Scene::Projection());
|
mProgram.setUniformValue(projection, Scene::getProjectionMatrix());
|
||||||
mProgram.setUniformValue(view, Scene::View());
|
mProgram.setUniformValue(view, Scene::getViewMatrix());
|
||||||
mProgram.setUniformValue(model, mTransform.toMatrix());
|
mProgram.setUniformValue(model, mTransform.toMatrix());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,6 +148,8 @@ void MeshRenderer::setColor(const QVector3D & color) {
|
||||||
mShape.mColors[i] = 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) {
|
void MeshRenderer::reallocateTexCoords(const TexCoords & t, unsigned dims) {
|
||||||
|
|
|
@ -15,31 +15,19 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace Qtk {
|
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 {
|
class QTKAPI MeshRenderer : public Object {
|
||||||
public:
|
public:
|
||||||
|
/*************************************************************************
|
||||||
|
* Typedefs
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/* Static QHash of all mesh objects within the scene. */
|
||||||
|
typedef QHash<QString, MeshRenderer *> MeshManager;
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Constructors / Destructors
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
// Delegate constructors
|
// Delegate constructors
|
||||||
MeshRenderer(
|
MeshRenderer(
|
||||||
const char * name, Vertices vertices, Indices indices,
|
const char * name, Vertices vertices, Indices indices,
|
||||||
|
@ -54,12 +42,28 @@ namespace Qtk {
|
||||||
MeshRenderer(const char * name, const ShapeBase & shape);
|
MeshRenderer(const char * name, const ShapeBase & shape);
|
||||||
~MeshRenderer() override;
|
~MeshRenderer() override;
|
||||||
|
|
||||||
// Retrieve a mesh by name stored within a static QHash
|
/*************************************************************************
|
||||||
static MeshRenderer * getInstance(const QString & name);
|
* Public Methods
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void draw();
|
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
|
// Draw types like GL_TRIANGLES, GL_POINTS, GL_LINES, etc
|
||||||
void setDrawType(int drawType) { mDrawType = drawType; }
|
void setDrawType(int drawType) { mDrawType = drawType; }
|
||||||
|
|
||||||
|
@ -105,21 +109,24 @@ namespace Qtk {
|
||||||
mVAO.release();
|
mVAO.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void enableAttributeArray(int location) {
|
/*************************************************************************
|
||||||
ShaderBindScope lock(&mProgram, mBound);
|
* Accessors
|
||||||
mVAO.bind();
|
************************************************************************/
|
||||||
mProgram.enableAttributeArray(location);
|
|
||||||
mVAO.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
void reallocateTexCoords(const TexCoords & t, unsigned dims = 2);
|
/**
|
||||||
|
* 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);
|
||||||
|
|
||||||
void reallocateNormals(const Normals & n, unsigned dims = 3);
|
Transform3D & getTransform() { return mTransform; }
|
||||||
|
|
||||||
// Static QHash of all mesh objects within the scene
|
|
||||||
typedef QHash<QString, MeshRenderer *> MeshManager;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/*************************************************************************
|
||||||
|
* Private Members
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
static MeshManager sInstances;
|
static MeshManager sInstances;
|
||||||
|
|
||||||
int mDrawType {};
|
int mDrawType {};
|
||||||
|
|
|
@ -9,9 +9,9 @@
|
||||||
|
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
|
||||||
#include <abstractscene.h>
|
|
||||||
#include <model.h>
|
#include <model.h>
|
||||||
#include <resourcemanager.h>
|
#include <resourcemanager.h>
|
||||||
|
#include <scene.h>
|
||||||
#include <texture.h>
|
#include <texture.h>
|
||||||
|
|
||||||
using namespace Qtk;
|
using namespace Qtk;
|
||||||
|
@ -97,8 +97,8 @@ void ModelMesh::draw(QOpenGLShaderProgram & shader) {
|
||||||
|
|
||||||
// Set Model View Projection values
|
// Set Model View Projection values
|
||||||
shader.setUniformValue("uModel", mTransform.toMatrix());
|
shader.setUniformValue("uModel", mTransform.toMatrix());
|
||||||
shader.setUniformValue("uView", Scene::View());
|
shader.setUniformValue("uView", Scene::getViewMatrix());
|
||||||
shader.setUniformValue("uProjection", Scene::Projection());
|
shader.setUniformValue("uProjection", Scene::getProjectionMatrix());
|
||||||
|
|
||||||
GLuint diffuseCount = 1;
|
GLuint diffuseCount = 1;
|
||||||
GLuint specularCount = 1;
|
GLuint specularCount = 1;
|
||||||
|
@ -180,21 +180,6 @@ void Model::flipTexture(const std::string & fileName, bool flipX, bool flipY) {
|
||||||
* Model Private Member Functions
|
* 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) {
|
void Model::loadModel(const std::string & path) {
|
||||||
Assimp::Importer import;
|
Assimp::Importer import;
|
||||||
|
|
||||||
|
@ -362,7 +347,7 @@ ModelMesh::Textures Model::loadMaterialTextures(
|
||||||
// If the texture has not yet been loaded
|
// If the texture has not yet been loaded
|
||||||
if(!skip) {
|
if(!skip) {
|
||||||
ModelTexture texture;
|
ModelTexture texture;
|
||||||
texture.mTexture = OpenGLTextureFactory::initTexture2D(
|
texture.mTexture = OpenGLTextureFactory::initTexture(
|
||||||
std::string(mDirectory + '/' + fileName.C_Str()).c_str(), false,
|
std::string(mDirectory + '/' + fileName.C_Str()).c_str(), false,
|
||||||
false);
|
false);
|
||||||
texture.mID = texture.mTexture->textureId();
|
texture.mID = texture.mTexture->textureId();
|
||||||
|
@ -380,7 +365,7 @@ ModelMesh::Textures Model::loadMaterialTextures(
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::sortModels() {
|
void Model::sortModels() {
|
||||||
auto cameraPos = Scene::Camera().transform();
|
auto cameraPos = Scene::getCamera().getTransform();
|
||||||
auto cameraDistance = [&cameraPos](const ModelMesh & a, const ModelMesh & b) {
|
auto cameraDistance = [&cameraPos](const ModelMesh & a, const ModelMesh & b) {
|
||||||
// Sort by the first vertex position in the model
|
// Sort by the first vertex position in the model
|
||||||
return (cameraPos.getTranslation().distanceToPoint(
|
return (cameraPos.getTranslation().distanceToPoint(
|
||||||
|
|
154
src/model.h
154
src/model.h
|
@ -28,14 +28,20 @@
|
||||||
#include <transform3D.h>
|
#include <transform3D.h>
|
||||||
|
|
||||||
namespace Qtk {
|
namespace Qtk {
|
||||||
|
/**
|
||||||
|
* 3D models will store this data for each vertex in geometry.
|
||||||
|
*/
|
||||||
struct QTKAPI ModelVertex {
|
struct QTKAPI ModelVertex {
|
||||||
QVector3D mPosition;
|
QVector3D mPosition;
|
||||||
QVector3D mNormal;
|
QVector3D mNormal;
|
||||||
|
QVector2D mTextureCoord;
|
||||||
QVector3D mTangent;
|
QVector3D mTangent;
|
||||||
QVector3D mBitangent;
|
QVector3D mBitangent;
|
||||||
QVector2D mTextureCoord;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Struct to store model textures. 3D Models may have multiple.
|
||||||
|
*/
|
||||||
struct QTKAPI ModelTexture {
|
struct QTKAPI ModelTexture {
|
||||||
GLuint mID {};
|
GLuint mID {};
|
||||||
QOpenGLTexture * mTexture {};
|
QOpenGLTexture * mTexture {};
|
||||||
|
@ -45,14 +51,25 @@ namespace Qtk {
|
||||||
|
|
||||||
class Model;
|
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 {
|
class QTKAPI ModelMesh : protected QOpenGLFunctions {
|
||||||
public:
|
public:
|
||||||
|
/*************************************************************************
|
||||||
|
* Typedefs
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
friend Model;
|
friend Model;
|
||||||
typedef std::vector<ModelVertex> Vertices;
|
typedef std::vector<ModelVertex> Vertices;
|
||||||
typedef std::vector<GLuint> Indices;
|
typedef std::vector<GLuint> Indices;
|
||||||
typedef std::vector<ModelTexture> Textures;
|
typedef std::vector<ModelTexture> Textures;
|
||||||
|
|
||||||
// Constructors, Destructors
|
/*************************************************************************
|
||||||
|
* Constructors, Destructors
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
ModelMesh(
|
ModelMesh(
|
||||||
Vertices vertices, Indices indices, Textures textures,
|
Vertices vertices, Indices indices, Textures textures,
|
||||||
const char * vertexShader = ":/model-basic.vert",
|
const char * vertexShader = ":/model-basic.vert",
|
||||||
|
@ -68,78 +85,177 @@ namespace Qtk {
|
||||||
|
|
||||||
~ModelMesh() = default;
|
~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); }
|
inline void draw() { draw(*mProgram); }
|
||||||
|
|
||||||
void draw(QOpenGLShaderProgram & shader);
|
void draw(QOpenGLShaderProgram & shader);
|
||||||
|
|
||||||
// ModelMesh Public Members
|
/*************************************************************************
|
||||||
|
* Public Members
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
Vertices mVertices {};
|
Vertices mVertices {};
|
||||||
Indices mIndices {};
|
Indices mIndices {};
|
||||||
Textures mTextures {};
|
Textures mTextures {};
|
||||||
Transform3D mTransform;
|
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 {
|
class QTKAPI Model : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
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(
|
inline Model(
|
||||||
const char * name, const char * path,
|
const char * name, const char * path,
|
||||||
const char * vertexShader = ":/model-basic.vert",
|
const char * vertexShader = ":/model-basic.vert",
|
||||||
const char * fragmentShader = ":/model-basic.frag") :
|
const char * fragmentShader = ":/model-basic.frag") :
|
||||||
mName(name),
|
mName(name),
|
||||||
mVertexShader(vertexShader), mFragmentShader(fragmentShader) {
|
mModelPath(path), mVertexShader(vertexShader),
|
||||||
|
mFragmentShader(fragmentShader) {
|
||||||
loadModel(path);
|
loadModel(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ~Model() override { mManager.remove(mName); }
|
inline ~Model() override { mManager.remove(mName); }
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Public Methods
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
void draw();
|
void draw();
|
||||||
void draw(QOpenGLShaderProgram & shader);
|
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(
|
void flipTexture(
|
||||||
const std::string & fileName, bool flipX = false, bool flipY = true);
|
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) {
|
template <typename T> void setUniform(const char * location, T value) {
|
||||||
for(auto & mesh : mMeshes) {
|
for(auto & mesh : mMeshes) {
|
||||||
mesh.mProgram->bind();
|
mesh.mProgram->bind();
|
||||||
|
|
||||||
mesh.mProgram->setUniformValue(location, value);
|
mesh.mProgram->setUniformValue(location, value);
|
||||||
|
|
||||||
mesh.mProgram->release();
|
mesh.mProgram->release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform3D mTransform;
|
/*************************************************************************
|
||||||
|
* 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);
|
static Model * getInstance(const char * name);
|
||||||
|
|
||||||
typedef QHash<QString, Model *> ModelManager;
|
Transform3D & getTransform() { return mTransform; }
|
||||||
|
|
||||||
private:
|
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 loadModel(const std::string & path);
|
||||||
|
|
||||||
void processNode(aiNode * node, const aiScene * scene);
|
void processNode(aiNode * node, const aiScene * scene);
|
||||||
|
|
||||||
ModelMesh processMesh(aiMesh * mesh, const aiScene * scene);
|
ModelMesh processMesh(aiMesh * mesh, const aiScene * scene);
|
||||||
|
|
||||||
ModelMesh::Textures loadMaterialTextures(
|
ModelMesh::Textures loadMaterialTextures(
|
||||||
aiMaterial * mat, aiTextureType type, const std::string & typeName);
|
aiMaterial * mat, aiTextureType type, const std::string & typeName);
|
||||||
|
|
||||||
void sortModels();
|
void sortModels();
|
||||||
|
|
||||||
// Model Private Members
|
/*************************************************************************
|
||||||
|
* Private Members
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/* The position of this model in 3D space */
|
||||||
|
Transform3D mTransform;
|
||||||
|
|
||||||
|
/* Static QHash used to store and access models globally. */
|
||||||
|
static ModelManager mManager;
|
||||||
|
|
||||||
|
/* Container to store N loaded textures for this model. */
|
||||||
ModelMesh::Textures mTexturesLoaded {};
|
ModelMesh::Textures mTexturesLoaded {};
|
||||||
|
/* Container to store N loaded meshes for this model. */
|
||||||
std::vector<ModelMesh> mMeshes {};
|
std::vector<ModelMesh> mMeshes {};
|
||||||
|
/* The directory this model and it's textures are stored. */
|
||||||
std::string mDirectory {};
|
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
|
} // namespace Qtk
|
||||||
|
|
||||||
|
|
62
src/object.h
62
src/object.h
|
@ -18,12 +18,24 @@
|
||||||
#include <texture.h>
|
#include <texture.h>
|
||||||
|
|
||||||
namespace Qtk {
|
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 {
|
class QTKAPI Object : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/*************************************************************************
|
||||||
|
* Typedefs
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
friend MeshRenderer;
|
friend MeshRenderer;
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Constructors / Destructors
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
// Initialize an object with no shape data assigned
|
// Initialize an object with no shape data assigned
|
||||||
explicit Object(const char * name) :
|
explicit Object(const char * name) :
|
||||||
mName(name), mVBO(QOpenGLBuffer::VertexBuffer), mBound(false) {}
|
mName(name), mVBO(QOpenGLBuffer::VertexBuffer), mBound(false) {}
|
||||||
|
@ -35,19 +47,39 @@ namespace Qtk {
|
||||||
|
|
||||||
~Object() override = default;
|
~Object() override = default;
|
||||||
|
|
||||||
inline const Colors & getColors() { return mShape.mColors; }
|
/*************************************************************************
|
||||||
|
* Accessors
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
inline const Indices & getIndexData() { return mShape.mIndices; }
|
[[nodiscard]] inline const Colors & getColors() const {
|
||||||
|
return mShape.mColors;
|
||||||
|
}
|
||||||
|
|
||||||
inline const Normals & getNormals() { return mShape.mNormals; }
|
[[nodiscard]] inline const Indices & getIndexData() const {
|
||||||
|
return mShape.mIndices;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline const Normals & getNormals() const {
|
||||||
|
return mShape.mNormals;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline const Shape & getShape() const { return mShape; }
|
[[nodiscard]] inline const Shape & getShape() const { return mShape; }
|
||||||
|
|
||||||
inline const TexCoords & getTexCoords() { return mShape.mTexCoords; }
|
[[nodiscard]] inline const TexCoords & getTexCoords() const {
|
||||||
|
return mShape.mTexCoords;
|
||||||
|
}
|
||||||
|
|
||||||
inline Texture & getTexture() { return mTexture; }
|
[[nodiscard]] inline const Texture & getTexture() const {
|
||||||
|
return mTexture;
|
||||||
|
}
|
||||||
|
|
||||||
inline const Vertices & getVertices() { return mShape.mVertices; }
|
[[nodiscard]] inline const Vertices & getVertices() const {
|
||||||
|
return mShape.mVertices;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Setters
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
virtual inline void setColors(const Colors & value) {
|
virtual inline void setColors(const Colors & value) {
|
||||||
mShape.mColors = value;
|
mShape.mColors = value;
|
||||||
|
@ -84,6 +116,10 @@ namespace Qtk {
|
||||||
mShape.mVertices = value;
|
mShape.mVertices = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Public Methods
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
virtual inline void bindShaders() {
|
virtual inline void bindShaders() {
|
||||||
mBound = true;
|
mBound = true;
|
||||||
mProgram.bind();
|
mProgram.bind();
|
||||||
|
@ -94,21 +130,19 @@ namespace Qtk {
|
||||||
mProgram.release();
|
mProgram.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*************************************************************************
|
||||||
|
* Private Members
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
QOpenGLShaderProgram mProgram;
|
||||||
QOpenGLBuffer mVBO, mNBO;
|
QOpenGLBuffer mVBO, mNBO;
|
||||||
QOpenGLVertexArrayObject mVAO;
|
QOpenGLVertexArrayObject mVAO;
|
||||||
|
|
||||||
Transform3D mTransform;
|
Transform3D mTransform;
|
||||||
Shape mShape;
|
Shape mShape;
|
||||||
Texture mTexture;
|
Texture mTexture;
|
||||||
const char * mName;
|
const char * mName;
|
||||||
bool mBound;
|
bool mBound;
|
||||||
|
|
||||||
private:
|
|
||||||
virtual inline void setTexture(QOpenGLTexture * value) {
|
|
||||||
mTexture.setTexture(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
QOpenGLShaderProgram mProgram;
|
|
||||||
};
|
};
|
||||||
} // namespace Qtk
|
} // namespace Qtk
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
|
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
|
|
||||||
#include <abstractscene.h>
|
|
||||||
#include <input.h>
|
#include <input.h>
|
||||||
#include <mesh.h>
|
#include <mesh.h>
|
||||||
#include <qtkwidget.h>
|
#include <qtkwidget.h>
|
||||||
|
#include <scene.h>
|
||||||
|
|
||||||
using namespace Qtk;
|
using namespace Qtk;
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@ QtkWidget::QtkWidget() : mScene(Q_NULLPTR), mDebugLogger(Q_NULLPTR) {
|
||||||
initializeWidget();
|
initializeWidget();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructor for using this widget in QtDesigner
|
|
||||||
QtkWidget::QtkWidget(QWidget * parent) :
|
QtkWidget::QtkWidget(QWidget * parent) :
|
||||||
QOpenGLWidget(parent), mScene(Q_NULLPTR), mDebugLogger(Q_NULLPTR) {
|
QOpenGLWidget(parent), mScene(Q_NULLPTR), mDebugLogger(Q_NULLPTR) {
|
||||||
initializeWidget();
|
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() {
|
void QtkWidget::initializeGL() {
|
||||||
initializeOpenGLFunctions();
|
initializeOpenGLFunctions();
|
||||||
// Connect the frameSwapped signal to call the update() function
|
// Connect the frameSwapped signal to call the update() function
|
||||||
|
@ -93,11 +74,19 @@ void QtkWidget::initializeGL() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtkWidget::resizeGL(int width, int height) {
|
void QtkWidget::resizeGL(int width, int height) {
|
||||||
Scene::Projection().setToIdentity();
|
Scene::getProjectionMatrix().setToIdentity();
|
||||||
Scene::Projection().perspective(
|
Scene::getProjectionMatrix().perspective(
|
||||||
45.0f, float(width) / float(height), 0.1f, 1000.0f);
|
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
|
* Protected Slots
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
@ -175,7 +164,7 @@ void QtkWidget::messageLogged(const QOpenGLDebugMessage & msg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Protected Helpers
|
* Protected Methods
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
void QtkWidget::keyPressEvent(QKeyEvent * event) {
|
void QtkWidget::keyPressEvent(QKeyEvent * event) {
|
||||||
|
@ -204,7 +193,7 @@ void QtkWidget::mouseReleaseEvent(QMouseEvent * event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Private Helpers
|
* Private Methods
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
void QtkWidget::initializeWidget() {
|
void QtkWidget::initializeWidget() {
|
||||||
|
@ -265,31 +254,31 @@ void QtkWidget::updateCameraInput() {
|
||||||
static const float rotSpeed = 0.5f;
|
static const float rotSpeed = 0.5f;
|
||||||
|
|
||||||
// Handle rotations
|
// Handle rotations
|
||||||
Scene::Camera().transform().rotate(
|
Scene::getCamera().getTransform().rotate(
|
||||||
-rotSpeed * Input::mouseDelta().x(), Camera3D::LocalUp);
|
-rotSpeed * Input::mouseDelta().x(), Camera3D::LocalUp);
|
||||||
Scene::Camera().transform().rotate(
|
Scene::getCamera().getTransform().rotate(
|
||||||
-rotSpeed * Input::mouseDelta().y(), Scene::Camera().right());
|
-rotSpeed * Input::mouseDelta().y(), Scene::getCamera().right());
|
||||||
|
|
||||||
// Handle translations
|
// Handle translations
|
||||||
QVector3D translation;
|
QVector3D translation;
|
||||||
if(Input::keyPressed(Qt::Key_W)) {
|
if(Input::keyPressed(Qt::Key_W)) {
|
||||||
translation += Scene::Camera().forward();
|
translation += Scene::getCamera().forward();
|
||||||
}
|
}
|
||||||
if(Input::keyPressed(Qt::Key_S)) {
|
if(Input::keyPressed(Qt::Key_S)) {
|
||||||
translation -= Scene::Camera().forward();
|
translation -= Scene::getCamera().forward();
|
||||||
}
|
}
|
||||||
if(Input::keyPressed(Qt::Key_A)) {
|
if(Input::keyPressed(Qt::Key_A)) {
|
||||||
translation -= Scene::Camera().right();
|
translation -= Scene::getCamera().right();
|
||||||
}
|
}
|
||||||
if(Input::keyPressed(Qt::Key_D)) {
|
if(Input::keyPressed(Qt::Key_D)) {
|
||||||
translation += Scene::Camera().right();
|
translation += Scene::getCamera().right();
|
||||||
}
|
}
|
||||||
if(Input::keyPressed(Qt::Key_Q)) {
|
if(Input::keyPressed(Qt::Key_Q)) {
|
||||||
translation -= Scene::Camera().up() / 2.0f;
|
translation -= Scene::getCamera().up() / 2.0f;
|
||||||
}
|
}
|
||||||
if(Input::keyPressed(Qt::Key_E)) {
|
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 <QOpenGLFunctions>
|
||||||
#include <QOpenGLWidget>
|
#include <QOpenGLWidget>
|
||||||
|
|
||||||
#include <abstractscene.h>
|
|
||||||
#include <qtkapi.h>
|
#include <qtkapi.h>
|
||||||
|
#include <scene.h>
|
||||||
|
|
||||||
namespace Qtk {
|
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 {
|
class QTKAPI QtkWidget : public QOpenGLWidget, protected QOpenGLFunctions {
|
||||||
Q_OBJECT;
|
Q_OBJECT;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructors
|
/*************************************************************************
|
||||||
|
* Contructors / Destructors
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default ctor will configure a QSurfaceFormat with default settings.
|
||||||
|
*/
|
||||||
QtkWidget();
|
QtkWidget();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Qt Designer will call this ctor when creating this widget as a child.
|
||||||
|
*
|
||||||
|
* @param parent The parent QWidget
|
||||||
|
*/
|
||||||
explicit QtkWidget(QWidget * parent);
|
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);
|
explicit QtkWidget(const QSurfaceFormat & format);
|
||||||
|
|
||||||
~QtkWidget() override;
|
~QtkWidget() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void teardownGL();
|
/*************************************************************************
|
||||||
|
* Private Methods
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
void teardownGL() { /* Nothing to teardown yet... */ }
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Inherited virtual Members
|
/*************************************************************************
|
||||||
void paintGL() override;
|
* Public Inherited Virtual Methods
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the widget is first constructed.
|
||||||
|
*/
|
||||||
void initializeGL() override;
|
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;
|
void resizeGL(int width, int height) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when OpenGL repaints the widget.
|
||||||
|
*/
|
||||||
|
void paintGL() override;
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Accessors
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
inline Qtk::Scene * getScene() { return mScene; }
|
inline Qtk::Scene * getScene() { return mScene; }
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Setters
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
inline void setScene(Qtk::Scene * scene) {
|
inline void setScene(Qtk::Scene * scene) {
|
||||||
delete mScene;
|
delete mScene;
|
||||||
|
|
||||||
mScene = scene;
|
mScene = scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
|
/*************************************************************************
|
||||||
|
* Qt Slots
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the `frameSwapped` signal is caught.
|
||||||
|
* See definition of initializeGL()
|
||||||
|
*/
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
#ifdef QTK_DEBUG
|
#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);
|
static void messageLogged(const QOpenGLDebugMessage & msg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Protected Helpers
|
|
||||||
protected:
|
protected:
|
||||||
|
/*************************************************************************
|
||||||
|
* Protected Methods
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
void keyPressEvent(QKeyEvent * event) override;
|
void keyPressEvent(QKeyEvent * event) override;
|
||||||
void keyReleaseEvent(QKeyEvent * event) override;
|
void keyReleaseEvent(QKeyEvent * event) override;
|
||||||
void mousePressEvent(QMouseEvent * event) override;
|
void mousePressEvent(QMouseEvent * event) override;
|
||||||
void mouseReleaseEvent(QMouseEvent * event) override;
|
void mouseReleaseEvent(QMouseEvent * event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Private helpers
|
/*************************************************************************
|
||||||
|
* Private Methods
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
void initializeWidget();
|
void initializeWidget();
|
||||||
static void updateCameraInput();
|
static void updateCameraInput();
|
||||||
|
|
||||||
Qtk::Scene * mScene;
|
|
||||||
#ifdef QTK_DEBUG
|
#ifdef QTK_DEBUG
|
||||||
void printContextInformation();
|
void printContextInformation();
|
||||||
QOpenGLDebugLogger * mDebugLogger;
|
QOpenGLDebugLogger * mDebugLogger;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Private Members
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
Qtk::Scene * mScene;
|
||||||
};
|
};
|
||||||
} // namespace Qtk
|
} // namespace Qtk
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
|
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
|
||||||
##############################################################################*/
|
##############################################################################*/
|
||||||
|
|
||||||
#include <abstractscene.h>
|
|
||||||
#include <camera3d.h>
|
#include <camera3d.h>
|
||||||
#include <resourcemanager.h>
|
#include <resourcemanager.h>
|
||||||
|
#include <scene.h>
|
||||||
#include <texture.h>
|
#include <texture.h>
|
||||||
|
|
||||||
using namespace Qtk;
|
using namespace Qtk;
|
||||||
|
@ -21,8 +21,8 @@ QMatrix4x4 Scene::mProjection;
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
Scene::Scene() {
|
Scene::Scene() {
|
||||||
mCamera.transform().setTranslation(0.0f, 0.0f, 20.0f);
|
mCamera.getTransform().setTranslation(0.0f, 0.0f, 20.0f);
|
||||||
mCamera.transform().setRotation(-5.0f, 0.0f, 1.0f, 0.0f);
|
mCamera.getTransform().setRotation(-5.0f, 0.0f, 1.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
Scene::~Scene() {
|
Scene::~Scene() {
|
||||||
|
@ -32,11 +32,10 @@ Scene::~Scene() {
|
||||||
for(auto & model : mModels) {
|
for(auto & model : mModels) {
|
||||||
delete model;
|
delete model;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete mSkybox;
|
delete mSkybox;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::privDraw() {
|
void Scene::privateDraw() {
|
||||||
if(!mInit) {
|
if(!mInit) {
|
||||||
initializeOpenGLFunctions();
|
initializeOpenGLFunctions();
|
||||||
init();
|
init();
|
|
@ -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 ##
|
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
|
||||||
##############################################################################*/
|
##############################################################################*/
|
||||||
|
|
||||||
#include <abstractscene.h>
|
#include <scene.h>
|
||||||
#include <skybox.h>
|
#include <skybox.h>
|
||||||
#include <texture.h>
|
#include <texture.h>
|
||||||
|
|
||||||
|
@ -32,8 +32,8 @@ Skybox::Skybox(const std::string & name) :
|
||||||
":/right.png", ":/top.png", ":/front.png", ":/left.png", ":/bottom.png",
|
":/right.png", ":/top.png", ":/front.png", ":/left.png", ":/bottom.png",
|
||||||
":/back.png", name) {}
|
":/back.png", name) {}
|
||||||
|
|
||||||
Skybox::Skybox(QOpenGLTexture * cubeMap, const std::string & name) :
|
Skybox::Skybox(QOpenGLTexture * cubeMap, const std::string & name) {
|
||||||
mTexture(cubeMap) {
|
mTexture.setTexture(cubeMap);
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,8 +49,8 @@ void Skybox::draw() {
|
||||||
mProgram.bind();
|
mProgram.bind();
|
||||||
mTexture.getOpenGLTexture().bind();
|
mTexture.getOpenGLTexture().bind();
|
||||||
|
|
||||||
mProgram.setUniformValue("uProjectionMatrix", Scene::Projection());
|
mProgram.setUniformValue("uProjectionMatrix", Scene::getProjectionMatrix());
|
||||||
mProgram.setUniformValue("uViewMatrix", Scene::Camera().toMatrix());
|
mProgram.setUniformValue("uViewMatrix", Scene::getCamera().toMatrix());
|
||||||
mProgram.setUniformValue("uTexture", 0);
|
mProgram.setUniformValue("uTexture", 0);
|
||||||
glDrawElements(
|
glDrawElements(
|
||||||
GL_TRIANGLES, mIndices.size(), GL_UNSIGNED_INT, mIndices.data());
|
GL_TRIANGLES, mIndices.size(), GL_UNSIGNED_INT, mIndices.data());
|
||||||
|
|
24
src/skybox.h
24
src/skybox.h
|
@ -21,13 +21,23 @@
|
||||||
#include <texture.h>
|
#include <texture.h>
|
||||||
|
|
||||||
namespace Qtk {
|
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 {
|
class QTKAPI Skybox : protected QOpenGLFunctions {
|
||||||
public:
|
public:
|
||||||
|
/*************************************************************************
|
||||||
|
* Constructors / Destructors
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
// Delegate this constructor to use default skybox images
|
// Delegate this constructor to use default skybox images
|
||||||
explicit Skybox(const std::string & name = "Skybox");
|
explicit Skybox(const std::string & name = "Skybox");
|
||||||
|
|
||||||
explicit Skybox(
|
explicit Skybox(
|
||||||
QOpenGLTexture * cubeMap, const std::string & name = "Skybox");
|
QOpenGLTexture * cubeMap, const std::string & name = "Skybox");
|
||||||
// Constructor, Destructor
|
|
||||||
Skybox(
|
Skybox(
|
||||||
const std::string & right, const std::string & top,
|
const std::string & right, const std::string & top,
|
||||||
const std::string & front, const std::string & left,
|
const std::string & front, const std::string & left,
|
||||||
|
@ -36,11 +46,23 @@ namespace Qtk {
|
||||||
|
|
||||||
~Skybox() = default;
|
~Skybox() = default;
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Public Methods
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
void draw();
|
void draw();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/*************************************************************************
|
||||||
|
* Private Methods
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Private Members
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
Vertices mVertices {};
|
Vertices mVertices {};
|
||||||
Indices mIndices {};
|
Indices mIndices {};
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ QImage * OpenGLTextureFactory::initImage(
|
||||||
return loadedImage;
|
return loadedImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
QOpenGLTexture * OpenGLTextureFactory::initTexture2D(
|
QOpenGLTexture * OpenGLTextureFactory::initTexture(
|
||||||
const char * texture, bool flipX, bool flipY) {
|
const char * texture, bool flipX, bool flipY) {
|
||||||
QImage * image = initImage(texture, flipX, flipY);
|
QImage * image = initImage(texture, flipX, flipY);
|
||||||
auto newTexture = new QOpenGLTexture(QOpenGLTexture::Target2D);
|
auto newTexture = new QOpenGLTexture(QOpenGLTexture::Target2D);
|
||||||
|
|
158
src/texture.h
158
src/texture.h
|
@ -9,30 +9,124 @@
|
||||||
#ifndef QTOPENGL_TEXTURE_H
|
#ifndef QTOPENGL_TEXTURE_H
|
||||||
#define QTOPENGL_TEXTURE_H
|
#define QTOPENGL_TEXTURE_H
|
||||||
|
|
||||||
|
#include <QOpenGLShaderProgram>
|
||||||
#include <QOpenGLTexture>
|
#include <QOpenGLTexture>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <qtkapi.h>
|
#include <qtkapi.h>
|
||||||
|
|
||||||
namespace Qtk {
|
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 {
|
class QTKAPI OpenGLTextureFactory {
|
||||||
public:
|
public:
|
||||||
|
/*************************************************************************
|
||||||
|
* Constructors / Destructors
|
||||||
|
************************************************************************/
|
||||||
~OpenGLTextureFactory() = default;
|
~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(
|
static QImage * initImage(
|
||||||
const char * image, bool flipX = false, bool flipY = false);
|
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);
|
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(
|
static QOpenGLTexture * initCubeMap(
|
||||||
const QImage & right, const QImage & top, const QImage & front,
|
const QImage & right, const QImage & top, const QImage & front,
|
||||||
const QImage & left, const QImage & bottom, const QImage & back);
|
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);
|
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(
|
static QOpenGLTexture * initCubeMap(
|
||||||
const char * right, const char * top, const char * front,
|
const char * right, const char * top, const char * front,
|
||||||
const char * left, const char * bottom, const char * back);
|
const char * left, const char * bottom, const char * back);
|
||||||
|
@ -42,48 +136,66 @@ namespace Qtk {
|
||||||
OpenGLTextureFactory() = default;
|
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 {
|
class Texture {
|
||||||
public:
|
public:
|
||||||
|
/*************************************************************************
|
||||||
|
* Typedefs
|
||||||
|
************************************************************************/
|
||||||
|
friend class Skybox;
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Constructors / Destructors
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
Texture() = default;
|
Texture() = default;
|
||||||
|
|
||||||
Texture(const Texture & value) {
|
Texture(const Texture & value) {
|
||||||
mOpenGLTexture = OpenGLTextureFactory::initTexture2D(value.mPath);
|
mOpenGLTexture = OpenGLTextureFactory::initTexture(value.mPath);
|
||||||
mPath = value.mPath;
|
mPath = value.mPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit Texture(
|
explicit Texture(
|
||||||
const char * path, bool flipX = false, bool flipY = false) :
|
const char * path, bool flipX = false, bool flipY = false) :
|
||||||
mOpenGLTexture(
|
mOpenGLTexture(OpenGLTextureFactory::initTexture(path, flipX, flipY)),
|
||||||
OpenGLTextureFactory::initTexture2D(path, flipX, flipY)),
|
|
||||||
mPath(path) {}
|
mPath(path) {}
|
||||||
|
|
||||||
explicit Texture(QOpenGLTexture * texture) : mOpenGLTexture(texture) {}
|
explicit Texture(QOpenGLTexture * texture) : mOpenGLTexture(texture) {}
|
||||||
|
|
||||||
~Texture() { mOpenGLTexture->destroy(); }
|
~Texture() { mOpenGLTexture->destroy(); }
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Accessors
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
[[nodiscard]] inline QOpenGLTexture & getOpenGLTexture() const {
|
[[nodiscard]] inline QOpenGLTexture & getOpenGLTexture() const {
|
||||||
return *mOpenGLTexture;
|
return *mOpenGLTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline std::string getPath() const { return mPath; }
|
[[nodiscard]] inline std::string getPath() const { return mPath; }
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Setters
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
void setTexture(
|
void setTexture(
|
||||||
const std::string & path, bool flipX = false, bool flipY = false) {
|
const std::string & path, bool flipX = false, bool flipY = false) {
|
||||||
mOpenGLTexture =
|
mOpenGLTexture =
|
||||||
OpenGLTextureFactory::initTexture2D(path.data(), flipX, flipY);
|
OpenGLTextureFactory::initTexture(path.data(), flipX, flipY);
|
||||||
mPath = path.data();
|
mPath = path.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTexture(
|
void setTexture(
|
||||||
const char * path, bool flipX = false, bool flipY = false) {
|
const char * path, bool flipX = false, bool flipY = false) {
|
||||||
mOpenGLTexture =
|
mOpenGLTexture = OpenGLTextureFactory::initTexture(path, flipX, flipY);
|
||||||
OpenGLTextureFactory::initTexture2D(path, flipX, flipY);
|
|
||||||
mPath = path;
|
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) {
|
virtual inline void setCubeMap(const char * path) {
|
||||||
mOpenGLTexture = OpenGLTextureFactory::initCubeMap(path);
|
mOpenGLTexture = OpenGLTextureFactory::initCubeMap(path);
|
||||||
mPath = path;
|
mPath = path;
|
||||||
|
@ -103,12 +215,24 @@ namespace Qtk {
|
||||||
right, top, front, left, bottom, back);
|
right, top, front, left, bottom, back);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Public Methods
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
[[nodiscard]] inline bool hasTexture() const {
|
[[nodiscard]] inline bool hasTexture() const {
|
||||||
return mOpenGLTexture != Q_NULLPTR;
|
return mOpenGLTexture != Q_NULLPTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/*************************************************************************
|
||||||
|
* Private Members
|
||||||
|
************************************************************************/
|
||||||
|
inline void setTexture(QOpenGLTexture * texture) {
|
||||||
|
mOpenGLTexture = texture;
|
||||||
|
}
|
||||||
|
|
||||||
QOpenGLTexture * mOpenGLTexture = Q_NULLPTR;
|
QOpenGLTexture * mOpenGLTexture = Q_NULLPTR;
|
||||||
|
/* Path to this texture on disk or Qt resource. */
|
||||||
const char * mPath {};
|
const char * mPath {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -23,15 +23,22 @@
|
||||||
#include <qtkapi.h>
|
#include <qtkapi.h>
|
||||||
|
|
||||||
namespace Qtk {
|
namespace Qtk {
|
||||||
|
/**
|
||||||
|
* Transform3D class to represent and modify object position in 3D space.
|
||||||
|
*/
|
||||||
class QTKAPI Transform3D {
|
class QTKAPI Transform3D {
|
||||||
public:
|
public:
|
||||||
// Constructors
|
/*************************************************************************
|
||||||
|
* Constructors, Destructors
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
inline Transform3D() :
|
inline Transform3D() :
|
||||||
m_dirty(true), mScale(1.0f, 1.0f, 1.0f),
|
m_dirty(true), mScale(1.0f, 1.0f, 1.0f),
|
||||||
mTranslation(0.0f, 0.0f, 0.0f) {}
|
mTranslation(0.0f, 0.0f, 0.0f) {}
|
||||||
|
|
||||||
//
|
/*************************************************************************
|
||||||
// Transformations
|
* Transformations
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
void translate(const QVector3D & dt);
|
void translate(const QVector3D & dt);
|
||||||
|
|
||||||
|
@ -72,8 +79,9 @@ namespace Qtk {
|
||||||
grow(QVector3D(factor, factor, factor));
|
grow(QVector3D(factor, factor, factor));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
/*************************************************************************
|
||||||
// Setters
|
* Setters
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
// Set object position
|
// Set object position
|
||||||
void setTranslation(const QVector3D & t);
|
void setTranslation(const QVector3D & t);
|
||||||
|
@ -102,8 +110,9 @@ namespace Qtk {
|
||||||
setRotation(QQuaternion::fromAxisAndAngle(ax, ay, az, angle));
|
setRotation(QQuaternion::fromAxisAndAngle(ax, ay, az, angle));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
/*************************************************************************
|
||||||
// Accessors
|
* Getters
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
[[nodiscard]] inline const QVector3D & getTranslation() const {
|
[[nodiscard]] inline const QVector3D & getTranslation() const {
|
||||||
return mTranslation;
|
return mTranslation;
|
||||||
|
@ -121,9 +130,17 @@ namespace Qtk {
|
||||||
[[nodiscard]] QVector3D getUp() const;
|
[[nodiscard]] QVector3D getUp() const;
|
||||||
[[nodiscard]] QVector3D getRight() const;
|
[[nodiscard]] QVector3D getRight() const;
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Public members
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
static const QVector3D LocalForward, LocalUp, LocalRight;
|
static const QVector3D LocalForward, LocalUp, LocalRight;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/*************************************************************************
|
||||||
|
* Private members
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
QVector3D mTranslation;
|
QVector3D mTranslation;
|
||||||
QQuaternion mRotation;
|
QQuaternion mRotation;
|
||||||
QVector3D mScale;
|
QVector3D mScale;
|
||||||
|
|
Loading…
Reference in New Issue