Clang format.
Some checks failed
All Builds / Qtk (-DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/ $CONFIG, -j $(nproc), ubuntu-latest) (push) Failing after 23s
All Builds / Qtk-Library (-DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/ $CONFIG, -j $(nproc), ubuntu-latest) (push) Failing after 22s
All Builds / Qtk-Plugins (-DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/ $CONFIG, -j $(nproc), ubuntu-latest) (push) Failing after 20s
All Builds / Qtk-Assimp-Targets (-DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/, ubuntu-latest) (push) Failing after 18s
Linting / Tidy (push) Failing after 24s
Linting / Format (app) (push) Failing after 23s
Linting / Format (src) (push) Failing after 23s
All Builds / Qtk (-DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/ $CONFIG, -j $(nproc), macos-latest) (push) Has been cancelled
All Builds / Qtk (-DCMAKE_PREFIX_PATH=D:/a/qtk/qtk/Qt/$QT_VERSION/mingw81_64/ $CONFIG, , windows-latest) (push) Has been cancelled
All Builds / Qtk-Library (-DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/ $CONFIG, -j $(nproc), macos-latest) (push) Has been cancelled
All Builds / Qtk-Library (-DCMAKE_PREFIX_PATH=D:/a/qtk/qtk/Qt/$QT_VERSION/mingw81_64/ $CONFIG, , windows-latest) (push) Has been cancelled
All Builds / Qtk-Plugins (-DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/ $CONFIG, -j $(nproc), macos-latest) (push) Has been cancelled
All Builds / Qtk-Plugins (-DCMAKE_PREFIX_PATH=D:/a/qtk/qtk/Qt/$QT_VERSION/mingw81_64/ $CONFIG, , windows-latest) (push) Has been cancelled
All Builds / Qtk-Assimp-Targets (-DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/, macos-latest) (push) Has been cancelled

This commit is contained in:
Shaun Reed 2025-03-08 11:47:19 -05:00
parent 1bed9545c9
commit 7fac6bafb4
49 changed files with 966 additions and 676 deletions

View File

@ -59,7 +59,7 @@ SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: true SpaceBeforeCpp11BracedList: true
SpaceBeforeCtorInitializerColon: true SpaceBeforeCtorInitializerColon: true
SpaceBeforeParens: Never SpaceBeforeParens: ControlStatementsExceptControlMacros
SpaceBeforeRangeBasedForLoopColon: true SpaceBeforeRangeBasedForLoopColon: true
SpacesBeforeTrailingComments: 2 SpacesBeforeTrailingComments: 2
SpaceInEmptyParentheses: false SpaceInEmptyParentheses: false

View File

@ -93,6 +93,7 @@ void ExampleScene::update()
top_triangle->getTransform().rotate(0.75f, 0.2f, 0.0f, 0.4f); top_triangle->getTransform().rotate(0.75f, 0.2f, 0.0f, 0.4f);
bottom_triangle->getTransform().rotate(0.75f, 0.0f, 0.2f, 0.4f); bottom_triangle->getTransform().rotate(0.75f, 0.0f, 0.2f, 0.4f);
MeshRenderer::getInstance("centerCube")->getTransform() MeshRenderer::getInstance("centerCube")
->getTransform()
.rotate(0.75f, 0.2f, 0.4f, 0.6f); .rotate(0.75f, 0.2f, 0.4f, 0.6f);
} }

View File

@ -11,7 +11,8 @@
#include <qtk/scene.h> #include <qtk/scene.h>
class ExampleScene : public Qtk::Scene { class ExampleScene : public Qtk::Scene
{
public: public:
explicit ExampleScene(); explicit ExampleScene();

View File

@ -11,7 +11,8 @@
#include "examplewidget.h" #include "examplewidget.h"
ExampleWidget::ExampleWidget(QWidget * parent) : ExampleWidget::ExampleWidget(QWidget * parent) :
QOpenGLWidget(parent), mScene(new ExampleScene) { QOpenGLWidget(parent), mScene(new ExampleScene)
{
// NOTE: The decorator pattern is used to save / load scenes in Qtk currently. // NOTE: The decorator pattern is used to save / load scenes in Qtk currently.
// The initializer above sets mScene to the concrete decorator ExampleScene. // The initializer above sets mScene to the concrete decorator ExampleScene.
// Qtk::SceneEmpty provides an empty scene as the concrete component. // Qtk::SceneEmpty provides an empty scene as the concrete component.
@ -27,7 +28,8 @@ ExampleWidget::ExampleWidget(QWidget * parent) :
setFocusPolicy(Qt::ClickFocus); setFocusPolicy(Qt::ClickFocus);
} }
void ExampleWidget::initializeGL() { void ExampleWidget::initializeGL()
{
initializeOpenGLFunctions(); initializeOpenGLFunctions();
connect(this, SIGNAL(frameSwapped()), this, SLOT(update())); connect(this, SIGNAL(frameSwapped()), this, SLOT(update()));
glEnable(GL_MULTISAMPLE); glEnable(GL_MULTISAMPLE);
@ -40,18 +42,21 @@ void ExampleWidget::initializeGL() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
} }
void ExampleWidget::resizeGL(int width, int height) { void ExampleWidget::resizeGL(int width, int height)
{
Qtk::Scene::getProjectionMatrix().setToIdentity(); Qtk::Scene::getProjectionMatrix().setToIdentity();
Qtk::Scene::getProjectionMatrix().perspective( Qtk::Scene::getProjectionMatrix().perspective(
45.0f, float(width) / float(height), 0.1f, 1000.0f); 45.0f, float(width) / float(height), 0.1f, 1000.0f);
} }
void ExampleWidget::paintGL() { void ExampleWidget::paintGL()
{
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
mScene->draw(); mScene->draw();
} }
void ExampleWidget::update() { void ExampleWidget::update()
{
mScene->update(); mScene->update();
QWidget::update(); QWidget::update();
} }

View File

@ -14,7 +14,8 @@
#include "examplescene.h" #include "examplescene.h"
class ExampleWidget : public QOpenGLWidget, protected QOpenGLFunctions { class ExampleWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
Q_OBJECT; Q_OBJECT;
public: public:

View File

@ -11,7 +11,8 @@
#include "examplewidget.h" #include "examplewidget.h"
int main(int argc, char * argv[]) { int main(int argc, char * argv[])
{
QApplication app(argc, argv); QApplication app(argc, argv);
auto window = new QMainWindow; auto window = new QMainWindow;

View File

@ -15,10 +15,13 @@
using namespace Qtk; using namespace Qtk;
DebugConsole::DebugConsole(QWidget * owner, const QString & key) : DebugConsole::DebugConsole(QWidget * owner, const QString & key) :
DebugConsole(owner, key, key + "Debugger") {} DebugConsole(owner, key, key + "Debugger")
{
}
DebugConsole::DebugConsole( DebugConsole::DebugConsole(QWidget * owner, const QString & key,
QWidget * owner, const QString & key, const QString & name) { const QString & name)
{
ui_ = new Ui::DebugConsole; ui_ = new Ui::DebugConsole;
ui_->setupUi(this); ui_->setupUi(this);
setObjectName(name); setObjectName(name);
@ -27,7 +30,7 @@ DebugConsole::DebugConsole(
setWindowTitle(name + " Debug Console"); setWindowTitle(name + " Debug Console");
auto qtkWidget = dynamic_cast<QtkWidget *>(owner); auto qtkWidget = dynamic_cast<QtkWidget *>(owner);
if(qtkWidget) { if (qtkWidget) {
connect(qtkWidget, &QtkWidget::sendLog, this, &DebugConsole::sendLog); connect(qtkWidget, &QtkWidget::sendLog, this, &DebugConsole::sendLog);
} }
} }

View File

@ -16,12 +16,15 @@
#include "qtkwidget.h" #include "qtkwidget.h"
namespace Ui { namespace Ui
{
class DebugConsole; class DebugConsole;
} }
namespace Qtk { namespace Qtk
class DebugConsole : public QDockWidget { {
class DebugConsole : public QDockWidget
{
Q_OBJECT; Q_OBJECT;
public: public:
@ -61,7 +64,8 @@ namespace Qtk {
* @param context The DebugContext to use for the message. * @param context The DebugContext to use for the message.
* Default value is Status. * Default value is Status.
*/ */
inline void sendLog(QString message, DebugContext context = Status) { inline void sendLog(QString message, DebugContext context = Status)
{
mConsole->setTextColor(logColor(context)); mConsole->setTextColor(logColor(context));
mConsole->append(logPrefix(message, context)); mConsole->append(logPrefix(message, context));
} }
@ -72,7 +76,8 @@ namespace Qtk {
* *
* @param name Base name for the DebugConsole window. * @param name Base name for the DebugConsole window.
*/ */
inline void setTitle(const QString& name) { inline void setTitle(const QString & name)
{
setWindowTitle(name + " Debug Console"); setWindowTitle(name + " Debug Console");
} }
@ -81,8 +86,9 @@ namespace Qtk {
* @param context Log context severity level. * @param context Log context severity level.
* @return QColor corresponding with the message context. * @return QColor corresponding with the message context.
*/ */
[[nodiscard]] QColor logColor(const DebugContext & context) const { [[nodiscard]] QColor logColor(const DebugContext & context) const
switch(context) { {
switch (context) {
case Status: case Status:
return Qt::GlobalColor::darkGray; return Qt::GlobalColor::darkGray;
case Debug: case Debug:
@ -105,10 +111,11 @@ namespace Qtk {
* @param context The log context severity level. * @param context The log context severity level.
* @return The log message prefixed with the DebugContext level. * @return The log message prefixed with the DebugContext level.
*/ */
[[nodiscard]] QString logPrefix( [[nodiscard]] QString logPrefix(QString & message,
QString & message, const DebugContext & context) { const DebugContext & context)
{
QString prefix; QString prefix;
switch(context) { switch (context) {
case Status: case Status:
prefix = "[Status]: "; prefix = "[Status]: ";
break; break;

View File

@ -11,7 +11,8 @@
#include "qtkmainwindow.h" #include "qtkmainwindow.h"
#include "qtkscene.h" #include "qtkscene.h"
int main(int argc, char * argv[]) { int main(int argc, char * argv[])
{
Q_INIT_RESOURCE(resources); Q_INIT_RESOURCE(resources);
QApplication a(argc, argv); QApplication a(argc, argv);

View File

@ -16,7 +16,8 @@ MainWindow * MainWindow::mainWindow_ = Q_NULLPTR;
* Constructors / Destructors * Constructors / Destructors
******************************************************************************/ ******************************************************************************/
MainWindow::MainWindow(QWidget * parent) : QMainWindow(parent) { MainWindow::MainWindow(QWidget * parent) : QMainWindow(parent)
{
ui_ = new Ui::MainWindow; ui_ = new Ui::MainWindow;
setObjectName("MainWindow"); setObjectName("MainWindow");
// For use in design mode using Qt Creator // For use in design mode using Qt Creator
@ -26,7 +27,7 @@ MainWindow::MainWindow(QWidget * parent) : QMainWindow(parent) {
// Initialize static container for all active QtkWidgets // Initialize static container for all active QtkWidgets
auto qtkWidgets = findChildren<Qtk::QtkWidget *>(); auto qtkWidgets = findChildren<Qtk::QtkWidget *>();
for(auto & qtkWidget : qtkWidgets) { for (auto & qtkWidget : qtkWidgets) {
// Qtk currently uses the decorator pattern to save / load scenes. // Qtk currently uses the decorator pattern to save / load scenes.
// This is a temporary solution and will be improved in the future. // This is a temporary solution and will be improved in the future.
qtkWidget->setScene(new QtkScene); qtkWidget->setScene(new QtkScene);
@ -35,12 +36,10 @@ MainWindow::MainWindow(QWidget * parent) : QMainWindow(parent) {
// Add GUI 'view' toolbar option to show debug console. // Add GUI 'view' toolbar option to show debug console.
ui_->menuView->addAction(qtkWidget->getActionToggleConsole()); ui_->menuView->addAction(qtkWidget->getActionToggleConsole());
// Refresh GUI widgets when scene or objects are updated. // Refresh GUI widgets when scene or objects are updated.
connect( connect(qtkWidget->getScene(), &Qtk::Scene::sceneUpdated, this,
qtkWidget->getScene(), &Qtk::Scene::sceneUpdated, this, &MainWindow::refreshScene);
&MainWindow::refreshScene); connect(qtkWidget, &Qtk::QtkWidget::objectFocusChanged, ui_->qtk__ToolBox,
connect( &Qtk::ToolBox::updateFocus);
qtkWidget, &Qtk::QtkWidget::objectFocusChanged, ui_->qtk__ToolBox,
&Qtk::ToolBox::updateFocus);
} }
// TODO: Fix / use MainWindow in Qt Designer to add these dock widgets. // TODO: Fix / use MainWindow in Qt Designer to add these dock widgets.
@ -60,7 +59,8 @@ MainWindow::MainWindow(QWidget * parent) : QMainWindow(parent) {
setWindowIcon(Qtk::getIcon()); setWindowIcon(Qtk::getIcon());
} }
MainWindow::~MainWindow() { MainWindow::~MainWindow()
{
delete ui_; delete ui_;
} }
@ -68,15 +68,17 @@ MainWindow::~MainWindow() {
* Public Methods * Public Methods
******************************************************************************/ ******************************************************************************/
MainWindow * MainWindow::getMainWindow() { MainWindow * MainWindow::getMainWindow()
if(mainWindow_ == Q_NULLPTR) { {
if (mainWindow_ == Q_NULLPTR) {
mainWindow_ = new MainWindow; mainWindow_ = new MainWindow;
} }
return mainWindow_; return mainWindow_;
} }
Qtk::QtkWidget * MainWindow::getQtkWidget(int64_t index) { Qtk::QtkWidget * MainWindow::getQtkWidget(int64_t index)
if(views_.size() <= index) { {
if (views_.size() <= index) {
return Q_NULLPTR; return Q_NULLPTR;
} }
auto it = views_.begin(); auto it = views_.begin();
@ -84,14 +86,16 @@ Qtk::QtkWidget * MainWindow::getQtkWidget(int64_t index) {
return it->second; return it->second;
} }
Qtk::QtkWidget * MainWindow::getQtkWidget(const QString & name) { Qtk::QtkWidget * MainWindow::getQtkWidget(const QString & name)
if(!views_.count(name)) { {
if (!views_.count(name)) {
return Q_NULLPTR; return Q_NULLPTR;
} }
return views_[name]; return views_[name];
} }
void MainWindow::refreshScene(const QString & sceneName) { void MainWindow::refreshScene(const QString & sceneName)
{
// TODO: Select TreeView using sceneName // TODO: Select TreeView using sceneName
ui_->qtk__TreeView->updateView(getQtkWidget()->getScene()); ui_->qtk__TreeView->updateView(getQtkWidget()->getScene());
} }

View File

@ -17,7 +17,8 @@
#include "debugconsole.h" #include "debugconsole.h"
#include "qtkwidget.h" #include "qtkwidget.h"
namespace Ui { namespace Ui
{
class MainWindow; class MainWindow;
} }
@ -25,7 +26,8 @@ namespace Ui {
* MainWindow class to provide an example of using a QtkWidget within a Qt * MainWindow class to provide an example of using a QtkWidget within a Qt
* window application. * window application.
*/ */
class MainWindow : public QMainWindow { class MainWindow : public QMainWindow
{
Q_OBJECT Q_OBJECT
public: public:

View File

@ -14,13 +14,15 @@ using namespace Qtk;
* Constructors, Destructors * Constructors, Destructors
******************************************************************************/ ******************************************************************************/
QtkScene::QtkScene() { QtkScene::QtkScene()
{
setSceneName("Qtk Scene"); setSceneName("Qtk Scene");
getCamera().getTransform().setTranslation(0.0f, 0.0f, 20.0f); getCamera().getTransform().setTranslation(0.0f, 0.0f, 20.0f);
getCamera().getTransform().setRotation(-5.0f, 0.0f, 1.0f, 0.0f); getCamera().getTransform().setRotation(-5.0f, 0.0f, 1.0f, 0.0f);
} }
QtkScene::~QtkScene() { QtkScene::~QtkScene()
{
delete mTestPhong; delete mTestPhong;
delete mTestSpecular; delete mTestSpecular;
delete mTestDiffuse; delete mTestDiffuse;
@ -31,7 +33,8 @@ QtkScene::~QtkScene() {
* Public Member Functions * Public Member Functions
******************************************************************************/ ******************************************************************************/
void QtkScene::init() { void QtkScene::init()
{
// Add a skybox to the scene using default cube map images and settings. // Add a skybox to the scene using default cube map images and settings.
setSkybox(new Qtk::Skybox("Skybox")); setSkybox(new Qtk::Skybox("Skybox"));
@ -116,8 +119,8 @@ void QtkScene::init() {
// NOTE: You no longer need to manually bind shader program to set uniforms. // 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. // + 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. // + Qtk will only bind / release if the shader program is not already bound.
mTestPhong->setShaders( mTestPhong->setShaders(":/shaders/solid-phong.vert",
":/shaders/solid-phong.vert", ":/shaders/solid-phong.frag"); ":/shaders/solid-phong.frag");
// For example this would technically not be efficient, because each one of // For example this would technically not be efficient, because each one of
// these calls will bind, set, release. We could instead bind, set N uniforms, // these calls will bind, set, release. We could instead bind, set N uniforms,
@ -143,16 +146,16 @@ void QtkScene::init() {
/* Example of a cube with no lighting applied */ /* Example of a cube with no lighting applied */
mesh = addObject(new Qtk::MeshRenderer("noLight", Cube(QTK_DRAW_ELEMENTS))); mesh = addObject(new Qtk::MeshRenderer("noLight", Cube(QTK_DRAW_ELEMENTS)));
mesh->getTransform().setTranslation(5.0f, 0.0f, -2.0f); mesh->getTransform().setTranslation(5.0f, 0.0f, -2.0f);
mesh->setShaders( mesh->setShaders(":/shaders/solid-perspective.vert",
":/shaders/solid-perspective.vert", ":/shaders/solid-perspective.frag"); ":/shaders/solid-perspective.frag");
mesh->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f)); mesh->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
// No light source needed for this lighting technique // No light source needed for this lighting technique
/* Initialize Ambient example cube */ /* Initialize Ambient example cube */
mTestAmbient = new Qtk::MeshRenderer("ambient", Cube()); mTestAmbient = new Qtk::MeshRenderer("ambient", Cube());
mTestAmbient->getTransform().setTranslation(7.0f, 0.0f, -2.0f); mTestAmbient->getTransform().setTranslation(7.0f, 0.0f, -2.0f);
mTestAmbient->setShaders( mTestAmbient->setShaders(":/shaders/solid-ambient.vert",
":/shaders/solid-ambient.vert", ":/shaders/solid-ambient.frag"); ":/shaders/solid-ambient.frag");
// Changing these uniform values will alter lighting effects. // 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));
@ -163,8 +166,8 @@ void QtkScene::init() {
/* Initialize Diffuse example cube */ /* Initialize Diffuse example cube */
mTestDiffuse = new Qtk::MeshRenderer("diffuse", Cube()); mTestDiffuse = new Qtk::MeshRenderer("diffuse", Cube());
mTestDiffuse->getTransform().setTranslation(9.0f, 0.0f, -2.0f); mTestDiffuse->getTransform().setTranslation(9.0f, 0.0f, -2.0f);
mTestDiffuse->setShaders( mTestDiffuse->setShaders(":/shaders/solid-diffuse.vert",
":/shaders/solid-diffuse.vert", ":/shaders/solid-diffuse.frag"); ":/shaders/solid-diffuse.frag");
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);
@ -179,8 +182,8 @@ void QtkScene::init() {
/* Initialize Specular example cube */ /* Initialize Specular example cube */
mTestSpecular = new Qtk::MeshRenderer("specular", Cube()); mTestSpecular = new Qtk::MeshRenderer("specular", Cube());
mTestSpecular->getTransform().setTranslation(11.0f, 0.0f, -2.0f); mTestSpecular->getTransform().setTranslation(11.0f, 0.0f, -2.0f);
mTestSpecular->setShaders( mTestSpecular->setShaders(":/shaders/solid-specular.vert",
":/shaders/solid-specular.vert", ":/shaders/solid-specular.frag"); ":/shaders/solid-specular.frag");
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);
@ -246,8 +249,8 @@ void QtkScene::init() {
model->setUniform("uLight.specular", QVector3D(1.0f, 1.0f, 1.0f)); model->setUniform("uLight.specular", QVector3D(1.0f, 1.0f, 1.0f));
// Light source for alienTest object. // Light source for alienTest object.
mesh = addObject(new Qtk::MeshRenderer( mesh = addObject(new Qtk::MeshRenderer("alienTestLight",
"alienTestLight", Triangle(Qtk::QTK_DRAW_ELEMENTS))); Triangle(Qtk::QTK_DRAW_ELEMENTS)));
mesh->getTransform().setTranslation(4.0f, 1.5f, 10.0f); mesh->getTransform().setTranslation(4.0f, 1.5f, 10.0f);
mesh->getTransform().scale(0.25f); mesh->getTransform().scale(0.25f);
// This function changes values we have allocated in a buffer, so init() after // This function changes values we have allocated in a buffer, so init() after
@ -290,8 +293,8 @@ void QtkScene::init() {
mesh->reallocateNormals(mesh->getNormals()); mesh->reallocateNormals(mesh->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
mesh = addObject(new Qtk::MeshRenderer( mesh = addObject(new Qtk::MeshRenderer("rgbNormalsCubeElementsTest",
"rgbNormalsCubeElementsTest", Cube(QTK_DRAW_ELEMENTS_NORMALS))); Cube(QTK_DRAW_ELEMENTS_NORMALS)));
mesh->getTransform().setTranslation(5.0f, 0.0f, 2.0f); mesh->getTransform().setTranslation(5.0f, 0.0f, 2.0f);
mesh->setShaders(":/shaders/rgb-normals.vert", ":/shaders/rgb-normals.frag"); mesh->setShaders(":/shaders/rgb-normals.vert", ":/shaders/rgb-normals.frag");
mesh->reallocateNormals(mesh->getNormals()); mesh->reallocateNormals(mesh->getNormals());
@ -321,8 +324,8 @@ void QtkScene::init() {
mesh->reallocateTexCoords(mesh->getTexCoords()); mesh->reallocateTexCoords(mesh->getTexCoords());
// Test drawing a cube with texture coordinates using glDrawElements // Test drawing a cube with texture coordinates using glDrawElements
mesh = addObject(new Qtk::MeshRenderer( mesh = addObject(new Qtk::MeshRenderer("uvCubeElementsTest",
"uvCubeElementsTest", Cube(QTK_DRAW_ELEMENTS_NORMALS))); Cube(QTK_DRAW_ELEMENTS_NORMALS)));
mesh->getTransform().setTranslation(-1.7f, 0.0f, -2.0f); mesh->getTransform().setTranslation(-1.7f, 0.0f, -2.0f);
mesh->setTexture(":/textures/crate.png"); mesh->setTexture(":/textures/crate.png");
mesh->setShaders(":/shaders/texture2d.vert", ":/shaders/texture2d.frag"); mesh->setShaders(":/shaders/texture2d.vert", ":/shaders/texture2d.frag");
@ -339,8 +342,8 @@ void QtkScene::init() {
addObject(new Qtk::MeshRenderer("testCubeMap", Cube(QTK_DRAW_ELEMENTS))); addObject(new Qtk::MeshRenderer("testCubeMap", Cube(QTK_DRAW_ELEMENTS)));
mesh->getTransform().setTranslation(-3.0f, 1.0f, -2.0f); mesh->getTransform().setTranslation(-3.0f, 1.0f, -2.0f);
mesh->getTransform().setRotation(45.0f, 0.0f, 1.0f, 0.0f); mesh->getTransform().setRotation(45.0f, 0.0f, 1.0f, 0.0f);
mesh->setShaders( mesh->setShaders(":/shaders/texture-cubemap.vert",
":/shaders/texture-cubemap.vert", ":/shaders/texture-cubemap.frag"); ":/shaders/texture-cubemap.frag");
mesh->setCubeMap(":/textures/crate.png"); mesh->setCubeMap(":/textures/crate.png");
mesh->setUniform("uTexture", 0); mesh->setUniform("uTexture", 0);
mesh->reallocateTexCoords(mesh->getTexCoords()); mesh->reallocateTexCoords(mesh->getTexCoords());
@ -354,15 +357,15 @@ void QtkScene::init() {
mesh->reallocateNormals(mesh->getNormals()); mesh->reallocateNormals(mesh->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
mesh = addObject(new Qtk::MeshRenderer( mesh = addObject(new Qtk::MeshRenderer("rgbTriangleArraysTest",
"rgbTriangleArraysTest", Triangle(QTK_DRAW_ARRAYS))); Triangle(QTK_DRAW_ARRAYS)));
mesh->getTransform().setTranslation(7.0f, 0.0f, 2.0f); mesh->getTransform().setTranslation(7.0f, 0.0f, 2.0f);
mesh->setShaders(":/shaders/rgb-normals.vert", ":/shaders/rgb-normals.frag"); mesh->setShaders(":/shaders/rgb-normals.vert", ":/shaders/rgb-normals.frag");
mesh->reallocateNormals(mesh->getNormals()); mesh->reallocateNormals(mesh->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
mesh = addObject(new Qtk::MeshRenderer( mesh = addObject(new Qtk::MeshRenderer("rgbTriangleElementsTest",
"rgbTriangleElementsTest", Triangle(QTK_DRAW_ELEMENTS_NORMALS))); Triangle(QTK_DRAW_ELEMENTS_NORMALS)));
mesh->getTransform().setTranslation(7.0f, 0.0f, 4.0f); mesh->getTransform().setTranslation(7.0f, 0.0f, 4.0f);
mesh->setShaders(":/shaders/rgb-normals.vert", ":/shaders/rgb-normals.frag"); mesh->setShaders(":/shaders/rgb-normals.vert", ":/shaders/rgb-normals.frag");
mesh->reallocateNormals(mesh->getNormals()); mesh->reallocateNormals(mesh->getNormals());
@ -378,8 +381,8 @@ void QtkScene::init() {
mesh->reallocateTexCoords(mesh->getTexCoords()); mesh->reallocateTexCoords(mesh->getTexCoords());
// Test drawing triangle with glDrawElements with texture coordinates // Test drawing triangle with glDrawElements with texture coordinates
mesh = addObject(new Qtk::MeshRenderer( mesh = addObject(new Qtk::MeshRenderer("testTriangleElementsUV",
"testTriangleElementsUV", Triangle(QTK_DRAW_ELEMENTS_NORMALS))); Triangle(QTK_DRAW_ELEMENTS_NORMALS)));
mesh->getTransform().setTranslation(-2.5f, 0.0f, -1.0f); mesh->getTransform().setTranslation(-2.5f, 0.0f, -1.0f);
mesh->setShaders(":/shaders/texture2d.vert", ":/shaders/texture2d.frag"); mesh->setShaders(":/shaders/texture2d.vert", ":/shaders/texture2d.frag");
mesh->setTexture(":/textures/crate.png"); mesh->setTexture(":/textures/crate.png");
@ -387,20 +390,20 @@ void QtkScene::init() {
mesh->reallocateTexCoords(mesh->getTexCoords()); mesh->reallocateTexCoords(mesh->getTexCoords());
} }
void QtkScene::draw() { void QtkScene::draw()
{
// WARNING: We must call the base class draw() function first. // WARNING: We must call the base class draw() function first.
// + This will handle rendering core scene components like the Skybox. // + This will handle rendering core scene components like the Skybox.
Scene::draw(); Scene::draw();
mTestPhong->bindShaders(); mTestPhong->bindShaders();
mTestPhong->setUniform( mTestPhong->setUniform("uModelInverseTransposed",
"uModelInverseTransposed", mTestPhong->getTransform().toMatrix().normalMatrix());
mTestPhong->getTransform().toMatrix().normalMatrix());
mTestPhong->setUniform( mTestPhong->setUniform(
"uLightPosition", "uLightPosition",
MeshRenderer::getInstance("phongLight")->getTransform().getTranslation()); MeshRenderer::getInstance("phongLight")->getTransform().getTranslation());
mTestPhong->setUniform( mTestPhong->setUniform("uCameraPosition",
"uCameraPosition", QtkScene::getCamera().getTransform().getTranslation()); QtkScene::getCamera().getTransform().getTranslation());
mTestPhong->releaseShaders(); mTestPhong->releaseShaders();
mTestPhong->draw(); mTestPhong->draw();
@ -414,10 +417,10 @@ void QtkScene::draw() {
mTestDiffuse->setUniform( mTestDiffuse->setUniform(
"uModelInverseTransposed", "uModelInverseTransposed",
mTestDiffuse->getTransform().toMatrix().normalMatrix()); mTestDiffuse->getTransform().toMatrix().normalMatrix());
mTestDiffuse->setUniform( mTestDiffuse->setUniform("uLightPosition",
"uLightPosition", MeshRenderer::getInstance("diffuseLight") MeshRenderer::getInstance("diffuseLight")
->getTransform() ->getTransform()
.getTranslation()); .getTranslation());
mTestDiffuse->setUniform( mTestDiffuse->setUniform(
"uCameraPosition", QtkScene::getCamera().getTransform().getTranslation()); "uCameraPosition", QtkScene::getCamera().getTransform().getTranslation());
mTestDiffuse->releaseShaders(); mTestDiffuse->releaseShaders();
@ -427,17 +430,18 @@ void QtkScene::draw() {
mTestSpecular->setUniform( mTestSpecular->setUniform(
"uModelInverseTransposed", "uModelInverseTransposed",
mTestSpecular->getTransform().toMatrix().normalMatrix()); mTestSpecular->getTransform().toMatrix().normalMatrix());
mTestSpecular->setUniform( mTestSpecular->setUniform("uLightPosition",
"uLightPosition", MeshRenderer::getInstance("specularLight") MeshRenderer::getInstance("specularLight")
->getTransform() ->getTransform()
.getTranslation()); .getTranslation());
mTestSpecular->setUniform( mTestSpecular->setUniform(
"uCameraPosition", QtkScene::getCamera().getTransform().getTranslation()); "uCameraPosition", QtkScene::getCamera().getTransform().getTranslation());
mTestSpecular->releaseShaders(); mTestSpecular->releaseShaders();
mTestSpecular->draw(); mTestSpecular->draw();
} }
void QtkScene::update() { void QtkScene::update()
{
auto mySpartan = Model::getInstance("My spartan"); auto mySpartan = Model::getInstance("My spartan");
mySpartan->getTransform().rotate(0.75f, 0.0f, 1.0f, 0.0f); mySpartan->getTransform().rotate(0.75f, 0.0f, 1.0f, 0.0f);
@ -449,8 +453,8 @@ void QtkScene::update() {
.getTranslation(); .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",
"uCameraPosition", QtkScene::getCamera().getTransform().getTranslation()); QtkScene::getCamera().getTransform().getTranslation());
auto posMatrix = alien->getTransform().toMatrix(); 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);
@ -463,8 +467,8 @@ void QtkScene::update() {
.getTranslation(); .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",
"uCameraPosition", QtkScene::getCamera().getTransform().getTranslation()); QtkScene::getCamera().getTransform().getTranslation());
posMatrix = spartan->getTransform().toMatrix(); 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);
@ -478,8 +482,8 @@ void QtkScene::update() {
position = position =
MeshRenderer::getInstance("testLight")->getTransform().getTranslation(); MeshRenderer::getInstance("testLight")->getTransform().getTranslation();
phong->setUniform("uLight.position", position); phong->setUniform("uLight.position", position);
phong->setUniform( phong->setUniform("uCameraPosition",
"uCameraPosition", QtkScene::getCamera().getTransform().getTranslation()); QtkScene::getCamera().getTransform().getTranslation());
posMatrix = phong->getTransform().toMatrix(); 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);
@ -489,8 +493,8 @@ void QtkScene::update() {
// Rotate lighting example cubes // Rotate lighting example cubes
mTestPhong->getTransform().rotate(0.75f, 0.5f, 0.3f, 0.2f); mTestPhong->getTransform().rotate(0.75f, 0.5f, 0.3f, 0.2f);
MeshRenderer::getInstance("noLight")->getTransform().rotate( MeshRenderer::getInstance("noLight")->getTransform().rotate(0.75f, 0.5f, 0.3f,
0.75f, 0.5f, 0.3f, 0.2f); 0.2f);
mTestAmbient->getTransform().rotate(0.75f, 0.5f, 0.3f, 0.2f); mTestAmbient->getTransform().rotate(0.75f, 0.5f, 0.3f, 0.2f);
mTestDiffuse->getTransform().rotate(0.75f, 0.5f, 0.3f, 0.2f); mTestDiffuse->getTransform().rotate(0.75f, 0.5f, 0.3f, 0.2f);
mTestSpecular->getTransform().rotate(0.75f, 0.5f, 0.3f, 0.2f); mTestSpecular->getTransform().rotate(0.75f, 0.5f, 0.3f, 0.2f);
@ -517,7 +521,7 @@ void QtkScene::update() {
->getTransform() ->getTransform()
.getTranslation() .getTranslation()
.x(); .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")

View File

@ -29,7 +29,8 @@
* *
* To create your own Scene from scratch see Qtk::Scene. * To create your own Scene from scratch see Qtk::Scene.
*/ */
class QtkScene : public Qtk::Scene { class QtkScene : public Qtk::Scene
{
public: public:
/*************************************************************************** /***************************************************************************
* Contructors / Destructors * Contructors / Destructors

View File

@ -32,11 +32,14 @@ using namespace Qtk;
QtkWidget::QtkWidget(QWidget * parent) : QtkWidget(parent, "QtkWidget") {} QtkWidget::QtkWidget(QWidget * parent) : QtkWidget(parent, "QtkWidget") {}
QtkWidget::QtkWidget(QWidget * parent, const QString & name) : QtkWidget::QtkWidget(QWidget * parent, const QString & name) :
QtkWidget(parent, name, Q_NULLPTR) {} QtkWidget(parent, name, Q_NULLPTR)
{
}
QtkWidget::QtkWidget(QWidget * parent, const QString & name, Scene * scene) : QtkWidget::QtkWidget(QWidget * parent, const QString & name, Scene * scene) :
QOpenGLWidget(parent), mDebugLogger(Q_NULLPTR), QOpenGLWidget(parent), mDebugLogger(Q_NULLPTR),
mConsole(new DebugConsole(this, name)), mScene(Q_NULLPTR) { mConsole(new DebugConsole(this, name)), mScene(Q_NULLPTR)
{
setAcceptDrops(true); setAcceptDrops(true);
setScene(scene); setScene(scene);
setObjectName(name); setObjectName(name);
@ -54,7 +57,8 @@ QtkWidget::QtkWidget(QWidget * parent, const QString & name, Scene * scene) :
setFocusPolicy(Qt::ClickFocus); setFocusPolicy(Qt::ClickFocus);
} }
QtkWidget::~QtkWidget() { QtkWidget::~QtkWidget()
{
makeCurrent(); makeCurrent();
teardownGL(); teardownGL();
} }
@ -63,7 +67,8 @@ QtkWidget::~QtkWidget() {
* Public Methods * Public Methods
******************************************************************************/ ******************************************************************************/
QAction * QtkWidget::getActionToggleConsole() { QAction * QtkWidget::getActionToggleConsole()
{
auto action = new QAction(mScene->getSceneName() + " debug console"); auto action = new QAction(mScene->getSceneName() + " debug console");
action->setCheckable(true); action->setCheckable(true);
action->setChecked(mConsoleActive); action->setChecked(mConsoleActive);
@ -72,7 +77,8 @@ QAction * QtkWidget::getActionToggleConsole() {
return action; return action;
} }
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
connect(this, SIGNAL(frameSwapped()), this, SLOT(update())); connect(this, SIGNAL(frameSwapped()), this, SLOT(update()));
@ -80,11 +86,10 @@ void QtkWidget::initializeGL() {
toggleConsole(); toggleConsole();
// Initialize OpenGL debug context // Initialize OpenGL debug context
mDebugLogger = new QOpenGLDebugLogger(this); mDebugLogger = new QOpenGLDebugLogger(this);
if(mDebugLogger->initialize()) { if (mDebugLogger->initialize()) {
qDebug() << "GL_DEBUG Debug Logger" << mDebugLogger << "\n"; qDebug() << "GL_DEBUG Debug Logger" << mDebugLogger << "\n";
connect( connect(mDebugLogger, SIGNAL(messageLogged(QOpenGLDebugMessage)), this,
mDebugLogger, SIGNAL(messageLogged(QOpenGLDebugMessage)), this, SLOT(messageLogged(QOpenGLDebugMessage)));
SLOT(messageLogged(QOpenGLDebugMessage)));
mDebugLogger->startLogging(); mDebugLogger->startLogging();
} }
@ -101,38 +106,41 @@ void QtkWidget::initializeGL() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
} }
void QtkWidget::resizeGL(int width, int height) { void QtkWidget::resizeGL(int width, int height)
{
Scene::getProjectionMatrix().setToIdentity(); Scene::getProjectionMatrix().setToIdentity();
Scene::getProjectionMatrix().perspective( Scene::getProjectionMatrix().perspective(45.0f, float(width) / float(height),
45.0f, float(width) / float(height), 0.1f, 1000.0f); 0.1f, 1000.0f);
} }
void QtkWidget::paintGL() { void QtkWidget::paintGL()
{
// Clear buffers and draw the scene if it is valid. // Clear buffers and draw the scene if it is valid.
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
if(mScene != Q_NULLPTR) { if (mScene != Q_NULLPTR) {
mScene->draw(); mScene->draw();
} }
} }
void QtkWidget::setScene(Scene * scene) { void QtkWidget::setScene(Scene * scene)
if(mScene != Q_NULLPTR) { {
if (mScene != Q_NULLPTR) {
delete mScene; delete mScene;
connect( connect(scene, &Scene::sceneUpdated, MainWindow::getMainWindow(),
scene, &Scene::sceneUpdated, MainWindow::getMainWindow(), &MainWindow::refreshScene);
&MainWindow::refreshScene);
} }
mScene = scene; mScene = scene;
if(mScene != Q_NULLPTR) { if (mScene != Q_NULLPTR) {
mConsole->setTitle(mScene->getSceneName()); mConsole->setTitle(mScene->getSceneName());
} else { } else {
mConsole->setTitle("Null Scene"); mConsole->setTitle("Null Scene");
} }
} }
void QtkWidget::toggleConsole() { void QtkWidget::toggleConsole()
if(mConsoleActive) { {
if (mConsoleActive) {
mConsole->setHidden(true); mConsole->setHidden(true);
mConsoleActive = false; mConsoleActive = false;
} else { } else {
@ -147,17 +155,19 @@ void QtkWidget::toggleConsole() {
* Protected Methods * Protected Methods
******************************************************************************/ ******************************************************************************/
void QtkWidget::dragEnterEvent(QDragEnterEvent * event) { void QtkWidget::dragEnterEvent(QDragEnterEvent * event)
if(event->mimeData()->hasFormat("text/plain")) { {
if (event->mimeData()->hasFormat("text/plain")) {
event->acceptProposedAction(); event->acceptProposedAction();
} }
} }
void QtkWidget::dropEvent(QDropEvent * event) { void QtkWidget::dropEvent(QDropEvent * event)
{
mConsole->sendLog(event->mimeData()->text()); mConsole->sendLog(event->mimeData()->text());
auto urls = event->mimeData()->urls(); auto urls = event->mimeData()->urls();
if(!urls.isEmpty()) { if (!urls.isEmpty()) {
if(urls.size() > 1) { if (urls.size() > 1) {
qDebug() << "Cannot accept drop of multiple files."; qDebug() << "Cannot accept drop of multiple files.";
event->ignore(); event->ignore();
return; return;
@ -165,7 +175,7 @@ void QtkWidget::dropEvent(QDropEvent * event) {
// TODO: Support other object types. // TODO: Support other object types.
auto url = urls.front(); auto url = urls.front();
if(url.fileName().endsWith(".obj")) { if (url.fileName().endsWith(".obj")) {
mScene->loadModel(url); mScene->loadModel(url);
event->acceptProposedAction(); event->acceptProposedAction();
} else { } else {
@ -175,8 +185,9 @@ void QtkWidget::dropEvent(QDropEvent * event) {
} }
} }
void QtkWidget::keyPressEvent(QKeyEvent * event) { void QtkWidget::keyPressEvent(QKeyEvent * event)
if(event->isAutoRepeat()) { {
if (event->isAutoRepeat()) {
// Do not repeat input while a key is held down // Do not repeat input while a key is held down
event->ignore(); event->ignore();
} else { } else {
@ -184,38 +195,43 @@ void QtkWidget::keyPressEvent(QKeyEvent * event) {
} }
} }
void QtkWidget::keyReleaseEvent(QKeyEvent * event) { void QtkWidget::keyReleaseEvent(QKeyEvent * event)
if(event->isAutoRepeat()) { {
if (event->isAutoRepeat()) {
event->ignore(); event->ignore();
} else { } else {
Input::registerKeyRelease(event->key()); Input::registerKeyRelease(event->key());
} }
} }
void QtkWidget::mousePressEvent(QMouseEvent * event) { void QtkWidget::mousePressEvent(QMouseEvent * event)
{
Input::registerMousePress(event->button()); Input::registerMousePress(event->button());
} }
void QtkWidget::mouseReleaseEvent(QMouseEvent * event) { void QtkWidget::mouseReleaseEvent(QMouseEvent * event)
{
Input::registerMouseRelease(event->button()); Input::registerMouseRelease(event->button());
} }
void QtkWidget::update() { void QtkWidget::update()
{
updateCameraInput(); updateCameraInput();
if(mScene != Q_NULLPTR) { if (mScene != Q_NULLPTR) {
mScene->update(); mScene->update();
} }
QWidget::update(); QWidget::update();
} }
void QtkWidget::messageLogged(const QOpenGLDebugMessage & msg) { void QtkWidget::messageLogged(const QOpenGLDebugMessage & msg)
{
QString error; QString error;
DebugContext context; DebugContext context;
// Format based on severity // Format based on severity
switch(msg.severity()) { switch (msg.severity()) {
case QOpenGLDebugMessage::NotificationSeverity: case QOpenGLDebugMessage::NotificationSeverity:
error += "--"; error += "--";
context = Status; context = Status;
@ -241,7 +257,7 @@ void QtkWidget::messageLogged(const QOpenGLDebugMessage & msg) {
case QOpenGLDebugMessage::c: \ case QOpenGLDebugMessage::c: \
error += #c; \ error += #c; \
break break
switch(msg.source()) { switch (msg.source()) {
CASE(APISource); CASE(APISource);
CASE(WindowSystemSource); CASE(WindowSystemSource);
CASE(ShaderCompilerSource); CASE(ShaderCompilerSource);
@ -259,7 +275,7 @@ void QtkWidget::messageLogged(const QOpenGLDebugMessage & msg) {
case QOpenGLDebugMessage::c: \ case QOpenGLDebugMessage::c: \
error += #c; \ error += #c; \
break break
switch(msg.type()) { switch (msg.type()) {
CASE(InvalidType); CASE(InvalidType);
CASE(ErrorType); CASE(ErrorType);
CASE(DeprecatedBehaviorType); CASE(DeprecatedBehaviorType);
@ -282,14 +298,16 @@ void QtkWidget::messageLogged(const QOpenGLDebugMessage & msg) {
* Private Methods * Private Methods
******************************************************************************/ ******************************************************************************/
void QtkWidget::teardownGL() { /* Nothing to teardown yet... */ void QtkWidget::teardownGL()
{ /* Nothing to teardown yet... */
} }
void QtkWidget::updateCameraInput() { void QtkWidget::updateCameraInput()
{
Input::update(); Input::update();
// Camera Transformation // Camera Transformation
if(Input::buttonPressed(Qt::LeftButton) if (Input::buttonPressed(Qt::LeftButton)
|| Input::buttonPressed(Qt::RightButton)) { || Input::buttonPressed(Qt::RightButton)) {
static const float transSpeed = 0.1f; static const float transSpeed = 0.1f;
static const float rotSpeed = 0.5f; static const float rotSpeed = 0.5f;
@ -301,29 +319,30 @@ void QtkWidget::updateCameraInput() {
// Handle translations // Handle translations
QVector3D translation; QVector3D translation;
if(Input::keyPressed(Qt::Key_W)) { if (Input::keyPressed(Qt::Key_W)) {
translation += Scene::getCamera().getForward(); translation += Scene::getCamera().getForward();
} }
if(Input::keyPressed(Qt::Key_S)) { if (Input::keyPressed(Qt::Key_S)) {
translation -= Scene::getCamera().getForward(); translation -= Scene::getCamera().getForward();
} }
if(Input::keyPressed(Qt::Key_A)) { if (Input::keyPressed(Qt::Key_A)) {
translation -= Scene::getCamera().getRight(); translation -= Scene::getCamera().getRight();
} }
if(Input::keyPressed(Qt::Key_D)) { if (Input::keyPressed(Qt::Key_D)) {
translation += Scene::getCamera().getRight(); translation += Scene::getCamera().getRight();
} }
if(Input::keyPressed(Qt::Key_Q)) { if (Input::keyPressed(Qt::Key_Q)) {
translation -= Scene::getCamera().getUp() / 2.0f; translation -= Scene::getCamera().getUp() / 2.0f;
} }
if(Input::keyPressed(Qt::Key_E)) { if (Input::keyPressed(Qt::Key_E)) {
translation += Scene::getCamera().getUp() / 2.0f; translation += Scene::getCamera().getUp() / 2.0f;
} }
Scene::getCamera().getTransform().translate(transSpeed * translation); Scene::getCamera().getTransform().translate(transSpeed * translation);
} }
} }
void QtkWidget::printContextInformation() { void QtkWidget::printContextInformation()
{
QString glType; QString glType;
QString glVersion; QString glVersion;
QString glProfile; QString glProfile;
@ -342,7 +361,7 @@ void QtkWidget::printContextInformation() {
case QSurfaceFormat::c: \ case QSurfaceFormat::c: \
glProfile = #c; \ glProfile = #c; \
break break
switch(format().profile()) { switch (format().profile()) {
CASE(NoProfile); CASE(NoProfile);
CASE(CoreProfile); CASE(CoreProfile);
CASE(CompatibilityProfile); CASE(CompatibilityProfile);

View File

@ -20,7 +20,8 @@
#include <qtk/qtkapi.h> #include <qtk/qtkapi.h>
#include <qtk/scene.h> #include <qtk/scene.h>
namespace Qtk { namespace Qtk
{
class DebugConsole; class DebugConsole;
/** /**
@ -29,7 +30,8 @@ namespace Qtk {
* This object has a Scene attached which manages the objects to render. * This object has a Scene attached which manages the objects to render.
* Client input is passed through this widget to control the camera view. * Client input is passed through this widget to control the camera view.
*/ */
class QtkWidget : public QOpenGLWidget, protected QOpenGLFunctions { class QtkWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
Q_OBJECT; Q_OBJECT;
public: public:
@ -103,7 +105,8 @@ namespace Qtk {
/** /**
* @return Pointer to the QOpenGLDebugLogger attached to this widget. * @return Pointer to the QOpenGLDebugLogger attached to this widget.
*/ */
inline QOpenGLDebugLogger * getOpenGLDebugLogger() { inline QOpenGLDebugLogger * getOpenGLDebugLogger()
{
return mDebugLogger; return mDebugLogger;
} }

View File

@ -16,34 +16,39 @@
using namespace Qtk; using namespace Qtk;
ToolBox::ToolBox(QWidget * parent) : QDockWidget(parent), ui(new Ui::ToolBox) { ToolBox::ToolBox(QWidget * parent) : QDockWidget(parent), ui(new Ui::ToolBox)
{
ui->setupUi(this); ui->setupUi(this);
setMinimumWidth(350); setMinimumWidth(350);
} }
void ToolBox::updateFocus(const QString & name) { void ToolBox::updateFocus(const QString & name)
{
auto object = auto object =
MainWindow::getMainWindow()->getQtkWidget()->getScene()->getObject(name); MainWindow::getMainWindow()->getQtkWidget()->getScene()->getObject(name);
if(object != Q_NULLPTR) { if (object != Q_NULLPTR) {
removePages(); removePages();
createPageProperties(object); createPageProperties(object);
createPageShader(object); createPageShader(object);
} }
} }
ToolBox::~ToolBox() { ToolBox::~ToolBox()
{
delete ui; delete ui;
} }
void ToolBox::removePages() { void ToolBox::removePages()
{
// Remove all existing pages. // Remove all existing pages.
for(size_t i = 0; i < ui->toolBox->count(); i++) { for (size_t i = 0; i < ui->toolBox->count(); i++) {
delete ui->toolBox->widget(i); delete ui->toolBox->widget(i);
ui->toolBox->removeItem(i); ui->toolBox->removeItem(i);
} }
} }
void ToolBox::createPageProperties(const Object * object) { void ToolBox::createPageProperties(const Object * object)
{
auto transform = object->getTransform(); auto transform = object->getTransform();
auto type = object->getType(); auto type = object->getType();
auto * widget = new QWidget; auto * widget = new QWidget;
@ -51,17 +56,16 @@ void ToolBox::createPageProperties(const Object * object) {
ui->toolBox->setCurrentWidget(widget); ui->toolBox->setCurrentWidget(widget);
auto * layout = new QFormLayout; auto * layout = new QFormLayout;
layout->addRow( layout->addRow(new QLabel(tr("Name:")),
new QLabel(tr("Name:")), new QLabel(object->getName().c_str())); new QLabel(object->getName().c_str()));
layout->addRow( layout->addRow(new QLabel(tr("Type:")),
new QLabel(tr("Type:")), new QLabel(type == Object::Type::QTK_MESH ? "Mesh" : "Model"));
new QLabel(type == Object::Type::QTK_MESH ? "Mesh" : "Model"));
auto rowLayout = new QHBoxLayout; auto rowLayout = new QHBoxLayout;
rowLayout->addWidget(new QLabel(tr("Translation:"))); rowLayout->addWidget(new QLabel(tr("Translation:")));
int minWidth = 75; int minWidth = 75;
for(size_t i = 0; i < 3; i++) { for (size_t i = 0; i < 3; i++) {
auto spinBox = new QDoubleSpinBox; auto spinBox = new QDoubleSpinBox;
spinBox->setMinimum(std::numeric_limits<double>::lowest()); spinBox->setMinimum(std::numeric_limits<double>::lowest());
spinBox->setSingleStep(0.1); spinBox->setSingleStep(0.1);
@ -69,25 +73,22 @@ void ToolBox::createPageProperties(const Object * object) {
spinBox->setFixedWidth(minWidth); spinBox->setFixedWidth(minWidth);
rowLayout->addWidget(spinBox); rowLayout->addWidget(spinBox);
if(i == 0) { if (i == 0) {
connect( connect(spinBox, &QDoubleSpinBox::valueChanged, object,
spinBox, &QDoubleSpinBox::valueChanged, object, &Object::setTranslationX);
&Object::setTranslationX); } else if (i == 1) {
} else if(i == 1) { connect(spinBox, &QDoubleSpinBox::valueChanged, object,
connect( &Object::setTranslationY);
spinBox, &QDoubleSpinBox::valueChanged, object, } else if (i == 2) {
&Object::setTranslationY); connect(spinBox, &QDoubleSpinBox::valueChanged, object,
} else if(i == 2) { &Object::setTranslationZ);
connect(
spinBox, &QDoubleSpinBox::valueChanged, object,
&Object::setTranslationZ);
} }
} }
layout->addRow(rowLayout); layout->addRow(rowLayout);
rowLayout = new QHBoxLayout; rowLayout = new QHBoxLayout;
rowLayout->addWidget(new QLabel(tr("Scale:"))); rowLayout->addWidget(new QLabel(tr("Scale:")));
for(size_t i = 0; i < 3; i++) { for (size_t i = 0; i < 3; i++) {
auto spinBox = new QDoubleSpinBox; auto spinBox = new QDoubleSpinBox;
spinBox->setMinimum(std::numeric_limits<double>::lowest()); spinBox->setMinimum(std::numeric_limits<double>::lowest());
spinBox->setSingleStep(0.1); spinBox->setSingleStep(0.1);
@ -95,22 +96,23 @@ void ToolBox::createPageProperties(const Object * object) {
spinBox->setFixedWidth(minWidth); spinBox->setFixedWidth(minWidth);
rowLayout->addWidget(spinBox); rowLayout->addWidget(spinBox);
if(i == 0) { if (i == 0) {
connect( connect(spinBox, &QDoubleSpinBox::valueChanged, object,
spinBox, &QDoubleSpinBox::valueChanged, object, &Object::setScaleX); &Object::setScaleX);
} else if(i == 1) { } else if (i == 1) {
connect( connect(spinBox, &QDoubleSpinBox::valueChanged, object,
spinBox, &QDoubleSpinBox::valueChanged, object, &Object::setScaleY); &Object::setScaleY);
} else if(i == 2) { } else if (i == 2) {
connect( connect(spinBox, &QDoubleSpinBox::valueChanged, object,
spinBox, &QDoubleSpinBox::valueChanged, object, &Object::setScaleZ); &Object::setScaleZ);
} }
} }
layout->addRow(rowLayout); layout->addRow(rowLayout);
widget->setLayout(layout); widget->setLayout(layout);
} }
void ToolBox::createPageShader(const Object * object) { void ToolBox::createPageShader(const Object * object)
{
// Shaders page. // Shaders page.
auto widget = new QWidget; auto widget = new QWidget;
ui->toolBox->addItem(widget, "Shaders"); ui->toolBox->addItem(widget, "Shaders");
@ -123,7 +125,7 @@ void ToolBox::createPageShader(const Object * object) {
auto shaderView = new QTextEdit; auto shaderView = new QTextEdit;
shaderView->setReadOnly(true); shaderView->setReadOnly(true);
auto vertexFile = QFile(object->getVertexShader().c_str()); auto vertexFile = QFile(object->getVertexShader().c_str());
if(vertexFile.exists()) { if (vertexFile.exists()) {
vertexFile.open(QIODeviceBase::ReadOnly); vertexFile.open(QIODeviceBase::ReadOnly);
shaderView->setText(vertexFile.readAll()); shaderView->setText(vertexFile.readAll());
vertexFile.close(); vertexFile.close();
@ -138,7 +140,7 @@ void ToolBox::createPageShader(const Object * object) {
shaderView = new QTextEdit; shaderView = new QTextEdit;
shaderView->setReadOnly(true); shaderView->setReadOnly(true);
auto fragmentfile = QFile(object->getFragmentShader().c_str()); auto fragmentfile = QFile(object->getFragmentShader().c_str());
if(fragmentfile.exists()) { if (fragmentfile.exists()) {
fragmentfile.open(QIODeviceBase::ReadOnly); fragmentfile.open(QIODeviceBase::ReadOnly);
shaderView->setText(fragmentfile.readAll()); shaderView->setText(fragmentfile.readAll());
fragmentfile.close(); fragmentfile.close();

View File

@ -18,12 +18,15 @@
#include "qtk/scene.h" #include "qtk/scene.h"
namespace Ui { namespace Ui
{
class ToolBox; class ToolBox;
} }
namespace Qtk { namespace Qtk
class ToolBox : public QDockWidget { {
class ToolBox : public QDockWidget
{
Q_OBJECT Q_OBJECT
public: public:

View File

@ -16,14 +16,15 @@
******************************************************************************/ ******************************************************************************/
Qtk::TreeView::TreeView(QWidget * parent) : Qtk::TreeView::TreeView(QWidget * parent) :
QDockWidget(parent), ui(new Ui::TreeView) { QDockWidget(parent), ui(new Ui::TreeView)
{
ui->setupUi(this); ui->setupUi(this);
connect( connect(ui->treeWidget, &QTreeWidget::itemDoubleClicked, this,
ui->treeWidget, &QTreeWidget::itemDoubleClicked, this, &TreeView::itemFocus);
&TreeView::itemFocus);
} }
Qtk::TreeView::~TreeView() { Qtk::TreeView::~TreeView()
{
delete ui; delete ui;
} }
@ -31,31 +32,33 @@ Qtk::TreeView::~TreeView() {
* Public Methods * Public Methods
******************************************************************************/ ******************************************************************************/
void Qtk::TreeView::updateView(const Qtk::Scene * scene) { void Qtk::TreeView::updateView(const Qtk::Scene * scene)
{
ui->treeWidget->clear(); ui->treeWidget->clear();
ui->treeWidget->setColumnCount(1); ui->treeWidget->setColumnCount(1);
mSceneName = scene->getSceneName(); mSceneName = scene->getSceneName();
auto objects = scene->getObjects(); auto objects = scene->getObjects();
for(const auto & object : objects) { for (const auto & object : objects) {
auto item = auto item =
new QTreeWidgetItem(QStringList(QString(object->getName().c_str()))); new QTreeWidgetItem(QStringList(QString(object->getName().c_str())));
ui->treeWidget->insertTopLevelItem(0, item); ui->treeWidget->insertTopLevelItem(0, item);
} }
} }
void Qtk::TreeView::itemFocus(QTreeWidgetItem * item, int column) { void Qtk::TreeView::itemFocus(QTreeWidgetItem * item, int column)
{
QString name = item->text(column); QString name = item->text(column);
auto scene = MainWindow::getMainWindow()->getQtkWidget()->getScene(); auto scene = MainWindow::getMainWindow()->getQtkWidget()->getScene();
auto & transform = Qtk::Scene::getCamera().getTransform(); auto & transform = Qtk::Scene::getCamera().getTransform();
auto object = scene->getObject(name); auto object = scene->getObject(name);
Transform3D * objectTransform; Transform3D * objectTransform;
// If the object is a mesh or model, focus the camera on it. // If the object is a mesh or model, focus the camera on it.
if(object == Q_NULLPTR) { if (object == Q_NULLPTR) {
qDebug() << "Attempt to get non-existing object with name '" << name qDebug() << "Attempt to get non-existing object with name '" << name
<< "'\n"; << "'\n";
} else if(object->getType() == Object::QTK_MESH) { } else if (object->getType() == Object::QTK_MESH) {
objectTransform = &dynamic_cast<MeshRenderer *>(object)->getTransform(); objectTransform = &dynamic_cast<MeshRenderer *>(object)->getTransform();
} else if(object->getType() == Object::QTK_MODEL) { } else if (object->getType() == Object::QTK_MODEL) {
objectTransform = &dynamic_cast<Model *>(object)->getTransform(); objectTransform = &dynamic_cast<Model *>(object)->getTransform();
} }
auto focusScale = objectTransform->getScale(); auto focusScale = objectTransform->getScale();
@ -68,5 +71,5 @@ void Qtk::TreeView::itemFocus(QTreeWidgetItem * item, int column) {
transform.translate(0.0f, 0.0f, 3.0f); transform.translate(0.0f, 0.0f, 3.0f);
// Emit signal from qtk widget for new object focus. Triggers GUI updates. // Emit signal from qtk widget for new object focus. Triggers GUI updates.
emit MainWindow::getMainWindow()->getQtkWidget()->objectFocusChanged(name); emit MainWindow::getMainWindow() -> getQtkWidget()->objectFocusChanged(name);
} }

View File

@ -17,12 +17,15 @@
#include <qtk/scene.h> #include <qtk/scene.h>
#include <QTreeWidgetItem> #include <QTreeWidgetItem>
namespace Ui { namespace Ui
{
class TreeView; class TreeView;
} }
namespace Qtk { namespace Qtk
class TreeView : public QDockWidget { {
class TreeView : public QDockWidget
{
Q_OBJECT Q_OBJECT
public: public:

View File

@ -19,12 +19,13 @@
* Constructors, Destructors * Constructors, Destructors
******************************************************************************/ ******************************************************************************/
WidgetPlugin::WidgetPlugin( WidgetPlugin::WidgetPlugin(QString group, QString class_name, QString include,
QString group, QString class_name, QString include, WidgetPlugin::Factory factory) :
WidgetPlugin::Factory factory) : m_group(std::move(group)), m_className(std::move(class_name)),
m_group(std::move(group)), m_includeFile(std::move(include)), m_factory(std::move(factory)),
m_className(std::move(class_name)), m_includeFile(std::move(include)), m_objectName(m_className)
m_factory(std::move(factory)), m_objectName(m_className) {} {
}
WidgetPlugin::WidgetPlugin(QObject * parent) : QObject(parent) {} WidgetPlugin::WidgetPlugin(QObject * parent) : QObject(parent) {}
@ -32,50 +33,61 @@ WidgetPlugin::WidgetPlugin(QObject * parent) : QObject(parent) {}
* Public Methods * Public Methods
******************************************************************************/ ******************************************************************************/
QString WidgetPlugin::group() const { QString WidgetPlugin::group() const
{
return m_group; return m_group;
} }
QString WidgetPlugin::name() const { QString WidgetPlugin::name() const
{
return m_className; return m_className;
} }
QString WidgetPlugin::includeFile() const { QString WidgetPlugin::includeFile() const
{
return m_includeFile; return m_includeFile;
} }
QWidget * WidgetPlugin::createWidget(QWidget * parent) { QWidget * WidgetPlugin::createWidget(QWidget * parent)
{
return m_factory(parent); return m_factory(parent);
} }
QString WidgetPlugin::toolTip() const { QString WidgetPlugin::toolTip() const
{
return QStringLiteral("A custom widget tool tip."); return QStringLiteral("A custom widget tool tip.");
} }
QString WidgetPlugin::whatsThis() const { QString WidgetPlugin::whatsThis() const
{
return QStringLiteral("Custom widget what's this?"); return QStringLiteral("Custom widget what's this?");
} }
QIcon WidgetPlugin::icon() const { QIcon WidgetPlugin::icon() const
{
return Qtk::getIcon(); return Qtk::getIcon();
} }
bool WidgetPlugin::isContainer() const { bool WidgetPlugin::isContainer() const
{
return true; return true;
} }
bool WidgetPlugin::isInitialized() const { bool WidgetPlugin::isInitialized() const
{
return m_initialized; return m_initialized;
} }
void WidgetPlugin::initialize(QDesignerFormEditorInterface *) { void WidgetPlugin::initialize(QDesignerFormEditorInterface *)
if(m_initialized) { {
if (m_initialized) {
return; return;
} }
m_initialized = true; m_initialized = true;
} }
QString WidgetPlugin::domXml() const { QString WidgetPlugin::domXml() const
{
return return
"<ui language=\"c++\">\n" "<ui language=\"c++\">\n"
" <widget class=\"" + m_className + "\" name=\"" + m_objectName + "\">\n" " <widget class=\"" + m_className + "\" name=\"" + m_objectName + "\">\n"

View File

@ -15,7 +15,8 @@
class QDESIGNER_WIDGET_EXPORT WidgetPlugin : class QDESIGNER_WIDGET_EXPORT WidgetPlugin :
public QObject, public QObject,
public QDesignerCustomWidgetInterface { public QDesignerCustomWidgetInterface
{
Q_OBJECT Q_OBJECT
Q_INTERFACES(QDesignerCustomWidgetInterface) Q_INTERFACES(QDesignerCustomWidgetInterface)
@ -26,8 +27,8 @@ class QDESIGNER_WIDGET_EXPORT WidgetPlugin :
* Contructors / Destructors * Contructors / Destructors
**************************************************************************/ **************************************************************************/
WidgetPlugin( WidgetPlugin(QString group, QString class_name, QString include,
QString group, QString class_name, QString include, Factory factory); Factory factory);
explicit WidgetPlugin(QObject * parent = nullptr); explicit WidgetPlugin(QObject * parent = nullptr);

View File

@ -19,7 +19,8 @@
******************************************************************************/ ******************************************************************************/
WidgetPluginCollection::WidgetPluginCollection(QObject * parent) : WidgetPluginCollection::WidgetPluginCollection(QObject * parent) :
QObject(parent), m_collectionName("Qtk Widget Collection") { QObject(parent), m_collectionName("Qtk Widget Collection")
{
m_collection = { m_collection = {
new WidgetPlugin( new WidgetPlugin(
m_collectionName, "Qtk::QtkWidget", "qtkwidget.h", m_collectionName, "Qtk::QtkWidget", "qtkwidget.h",
@ -38,6 +39,7 @@ WidgetPluginCollection::WidgetPluginCollection(QObject * parent) :
******************************************************************************/ ******************************************************************************/
QList<QDesignerCustomWidgetInterface *> WidgetPluginCollection::customWidgets() QList<QDesignerCustomWidgetInterface *> WidgetPluginCollection::customWidgets()
const { const
{
return m_collection; return m_collection;
} }

View File

@ -14,7 +14,8 @@
class WidgetPluginCollection : class WidgetPluginCollection :
public QObject, public QObject,
public QDesignerCustomWidgetCollectionInterface { public QDesignerCustomWidgetCollectionInterface
{
Q_OBJECT Q_OBJECT
// Since we're exporting a collection, this is the only plugin metadata // Since we're exporting a collection, this is the only plugin metadata
// needed. We don't need this for-each widget in the collection. // needed. We don't need this for-each widget in the collection.
@ -36,7 +37,8 @@ class WidgetPluginCollection :
/** /**
* @return QList of all custom widgets pointers. * @return QList of all custom widgets pointers.
*/ */
[[nodiscard]] QList<QDesignerCustomWidgetInterface *> customWidgets() const override; [[nodiscard]] QList<QDesignerCustomWidgetInterface *> customWidgets()
const override;
private: private:
/*************************************************************************** /***************************************************************************

View File

@ -22,7 +22,8 @@ const QVector3D Camera3D::LocalRight(1.0f, 0.0f, 0.0f);
* Public Methods * Public Methods
******************************************************************************/ ******************************************************************************/
const QMatrix4x4 & Camera3D::toMatrix() { const QMatrix4x4 & Camera3D::toMatrix()
{
mWorld.setToIdentity(); mWorld.setToIdentity();
// Qt6 renamed QMatrix4x4::conjugate() to conjugated() // Qt6 renamed QMatrix4x4::conjugate() to conjugated()
mWorld.rotate(mTransform.getRotation().conjugated()); mWorld.rotate(mTransform.getRotation().conjugated());
@ -34,17 +35,20 @@ const QMatrix4x4 & Camera3D::toMatrix() {
* Qt Streams * Qt Streams
******************************************************************************/ ******************************************************************************/
QDataStream & operator<<(QDataStream & out, Camera3D & transform) { QDataStream & operator<<(QDataStream & out, Camera3D & transform)
{
out << transform.getTransform(); out << transform.getTransform();
return out; return out;
} }
QDataStream & operator>>(QDataStream & in, Camera3D & transform) { QDataStream & operator>>(QDataStream & in, Camera3D & transform)
{
in >> transform.getTransform(); 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.getTranslation().x() << ", " dbg << "Position: <" << transform.getTranslation().x() << ", "
<< transform.getTranslation().y() << ", " << transform.getTranslation().y() << ", "

View File

@ -14,8 +14,10 @@
#include "qtkapi.h" #include "qtkapi.h"
#include "transform3D.h" #include "transform3D.h"
namespace Qtk { namespace Qtk
class QTKAPI Camera3D { {
class QTKAPI Camera3D
{
public: public:
/************************************************************************* /*************************************************************************
* Static Public Constants * Static Public Constants
@ -37,35 +39,40 @@ namespace Qtk {
/** /**
* @return Current translation of the camera as a QVector3D. * @return Current translation of the camera as a QVector3D.
*/ */
[[nodiscard]] inline const QVector3D & getTranslation() const { [[nodiscard]] inline const QVector3D & getTranslation() const
{
return mTransform.getTranslation(); return mTransform.getTranslation();
} }
/** /**
* @return Current rotation of this camera as a QQuaternion. * @return Current rotation of this camera as a QQuaternion.
*/ */
[[nodiscard]] inline const QQuaternion & getRotation() const { [[nodiscard]] inline const QQuaternion & getRotation() const
{
return mTransform.getRotation(); return mTransform.getRotation();
} }
/** /**
* @return QVector3D for the forward vector of the camera. * @return QVector3D for the forward vector of the camera.
*/ */
[[nodiscard]] inline QVector3D getForward() const { [[nodiscard]] inline QVector3D getForward() const
{
return mTransform.getRotation().rotatedVector(LocalForward); return mTransform.getRotation().rotatedVector(LocalForward);
} }
/** /**
* @return QVector3D for the right vector of the camera. * @return QVector3D for the right vector of the camera.
*/ */
[[nodiscard]] inline QVector3D getRight() const { [[nodiscard]] inline QVector3D getRight() const
{
return mTransform.getRotation().rotatedVector(LocalRight); return mTransform.getRotation().rotatedVector(LocalRight);
} }
/** /**
* @return QVector3D for the up vector of the camera. * @return QVector3D for the up vector of the camera.
*/ */
[[nodiscard]] inline QVector3D getUp() const { [[nodiscard]] inline QVector3D getUp() const
{
return mTransform.getRotation().rotatedVector(LocalUp); return mTransform.getRotation().rotatedVector(LocalUp);
} }

View File

@ -33,10 +33,13 @@ template <typename T> struct InputInstance : std::pair<T, Input::InputState> {
inline InputInstance(T value) : base_class(value, Input::InputInvalid) {} inline InputInstance(T value) : base_class(value, Input::InputInvalid) {}
inline InputInstance(T value, Input::InputState state) : inline InputInstance(T value, Input::InputState state) :
base_class(value, state) {} base_class(value, state)
{
}
// Allows use of std::find to search for a key's InputInstance // Allows use of std::find to search for a key's InputInstance
inline bool operator==(const InputInstance & rhs) const { inline bool operator==(const InputInstance & rhs) const
{
return this->first == rhs.first; return this->first == rhs.first;
} }
}; };
@ -67,7 +70,8 @@ static QPoint sg_mouseDelta;
* @param value The key to search for. * @param value The key to search for.
* @return Iterator to the found element or the end iterator if not found. * @return Iterator to the found element or the end iterator if not found.
*/ */
static inline KeyContainer::iterator FindKey(Qt::Key value) { static inline KeyContainer::iterator FindKey(Qt::Key value)
{
return std::find(sg_keyInstances.begin(), sg_keyInstances.end(), value); return std::find(sg_keyInstances.begin(), sg_keyInstances.end(), value);
} }
@ -77,7 +81,8 @@ static inline KeyContainer::iterator FindKey(Qt::Key value) {
* @param value The mouse button to search for. * @param value The mouse button to search for.
* @return Iterator to the found element or the end iterator if not found. * @return Iterator to the found element or the end iterator if not found.
*/ */
static inline ButtonContainer::iterator FindButton(Qt::MouseButton value) { static inline ButtonContainer::iterator FindButton(Qt::MouseButton value)
{
return std::find(sg_buttonInstances.begin(), sg_buttonInstances.end(), value); return std::find(sg_buttonInstances.begin(), sg_buttonInstances.end(), value);
} }
@ -89,7 +94,8 @@ static inline ButtonContainer::iterator FindButton(Qt::MouseButton value) {
* @return True if the InputInstance is in the released state. * @return True if the InputInstance is in the released state.
*/ */
template <typename TPair> template <typename TPair>
static inline bool CheckReleased(const TPair & instance) { static inline bool CheckReleased(const TPair & instance)
{
return instance.second == Input::InputReleased; return instance.second == Input::InputReleased;
} }
@ -99,8 +105,9 @@ static inline bool CheckReleased(const TPair & instance) {
* @tparam TPair KeyInstance or ButtonInstance. * @tparam TPair KeyInstance or ButtonInstance.
* @param instance The InputInstance to update. * @param instance The InputInstance to update.
*/ */
template <typename TPair> static inline void UpdateStates(TPair & instance) { template <typename TPair> static inline void UpdateStates(TPair & instance)
switch(instance.second) { {
switch (instance.second) {
case Input::InputRegistered: case Input::InputRegistered:
instance.second = Input::InputTriggered; instance.second = Input::InputTriggered;
break; break;
@ -121,7 +128,8 @@ template <typename TPair> static inline void UpdateStates(TPair & instance) {
* @tparam Container The type of container, KeyContainer or ButtonContainer. * @tparam Container The type of container, KeyContainer or ButtonContainer.
* @param container The InputInstance container to update. * @param container The InputInstance container to update.
*/ */
template <typename Container> static inline void Update(Container & container) { template <typename Container> static inline void Update(Container & container)
{
typedef typename Container::iterator Iter; typedef typename Container::iterator Iter;
typedef typename Container::value_type TPair; typedef typename Container::value_type TPair;
@ -138,7 +146,8 @@ template <typename Container> static inline void Update(Container & container) {
* Static Public Methods * Static Public Methods
******************************************************************************/ ******************************************************************************/
void Input::update() { void Input::update()
{
// Update Mouse Delta // Update Mouse Delta
sg_mousePrevPosition = sg_mouseCurrPosition; sg_mousePrevPosition = sg_mouseCurrPosition;
sg_mouseCurrPosition = QCursor::pos(); sg_mouseCurrPosition = QCursor::pos();
@ -149,53 +158,62 @@ void Input::update() {
Update(sg_keyInstances); Update(sg_keyInstances);
} }
void Input::registerKeyPress(int k) { void Input::registerKeyPress(int k)
{
auto it = FindKey((Qt::Key)k); auto it = FindKey((Qt::Key)k);
if(it == sg_keyInstances.end()) { if (it == sg_keyInstances.end()) {
sg_keyInstances.emplace_back((Qt::Key)k, InputRegistered); sg_keyInstances.emplace_back((Qt::Key)k, InputRegistered);
} }
} }
void Input::registerKeyRelease(int k) { void Input::registerKeyRelease(int k)
{
auto it = FindKey((Qt::Key)k); auto it = FindKey((Qt::Key)k);
if(it != sg_keyInstances.end()) { if (it != sg_keyInstances.end()) {
it->second = InputUnregistered; it->second = InputUnregistered;
} }
} }
void Input::registerMousePress(Qt::MouseButton button) { void Input::registerMousePress(Qt::MouseButton button)
{
auto it = FindButton(button); auto it = FindButton(button);
if(it == sg_buttonInstances.end()) { if (it == sg_buttonInstances.end()) {
sg_buttonInstances.emplace_back(button, InputRegistered); sg_buttonInstances.emplace_back(button, InputRegistered);
} }
} }
void Input::registerMouseRelease(Qt::MouseButton button) { void Input::registerMouseRelease(Qt::MouseButton button)
{
auto it = FindButton(button); auto it = FindButton(button);
if(it != sg_buttonInstances.end()) { if (it != sg_buttonInstances.end()) {
it->second = InputUnregistered; it->second = InputUnregistered;
} }
} }
void Input::reset() { void Input::reset()
{
sg_keyInstances.clear(); sg_keyInstances.clear();
sg_buttonInstances.clear(); sg_buttonInstances.clear();
} }
Input::InputState Input::keyState(Qt::Key k) { Input::InputState Input::keyState(Qt::Key k)
{
auto it = FindKey(k); auto it = FindKey(k);
return (it != sg_keyInstances.end()) ? it->second : InputInvalid; return (it != sg_keyInstances.end()) ? it->second : InputInvalid;
} }
Input::InputState Input::buttonState(Qt::MouseButton button) { Input::InputState Input::buttonState(Qt::MouseButton button)
{
auto it = FindButton(button); auto it = FindButton(button);
return (it != sg_buttonInstances.end()) ? it->second : InputInvalid; return (it != sg_buttonInstances.end()) ? it->second : InputInvalid;
} }
QPoint Input::mousePosition() { QPoint Input::mousePosition()
{
return QCursor::pos(); return QCursor::pos();
} }
QPoint Input::mouseDelta() { QPoint Input::mouseDelta()
{
return sg_mouseDelta; return sg_mouseDelta;
} }

View File

@ -14,8 +14,10 @@
#include "qtkapi.h" #include "qtkapi.h"
namespace Qtk { namespace Qtk
class QTKAPI Input { {
class QTKAPI Input
{
public: public:
/************************************************************************* /*************************************************************************
* Typedefs * Typedefs
@ -84,7 +86,8 @@ namespace Qtk {
* @param key Key to check state. * @param key Key to check state.
* @return True if the key is in InputTriggered state. * @return True if the key is in InputTriggered state.
*/ */
inline static bool keyTriggered(Qt::Key key) { inline static bool keyTriggered(Qt::Key key)
{
return keyState(key) == InputTriggered; return keyState(key) == InputTriggered;
} }
@ -92,7 +95,8 @@ namespace Qtk {
* @param key Key to check state. * @param key Key to check state.
* @return True if the key is in InputPressed state. * @return True if the key is in InputPressed state.
*/ */
inline static bool keyPressed(Qt::Key key) { inline static bool keyPressed(Qt::Key key)
{
return keyState(key) == InputPressed; return keyState(key) == InputPressed;
} }
@ -100,7 +104,8 @@ namespace Qtk {
* @param key Key to check state. * @param key Key to check state.
* @return True if the key is in InputReleased state. * @return True if the key is in InputReleased state.
*/ */
inline static bool keyReleased(Qt::Key key) { inline static bool keyReleased(Qt::Key key)
{
return keyState(key) == InputReleased; return keyState(key) == InputReleased;
} }
@ -108,7 +113,8 @@ namespace Qtk {
* @param button Mouse button to check state. * @param button Mouse button to check state.
* @return True if the key is in InputTriggered state. * @return True if the key is in InputTriggered state.
*/ */
inline static bool buttonTriggered(Qt::MouseButton button) { inline static bool buttonTriggered(Qt::MouseButton button)
{
return buttonState(button) == InputTriggered; return buttonState(button) == InputTriggered;
} }
@ -116,7 +122,8 @@ namespace Qtk {
* @param button Mouse button to check state. * @param button Mouse button to check state.
* @return True if the key is in InputPressed state. * @return True if the key is in InputPressed state.
*/ */
inline static bool buttonPressed(Qt::MouseButton button) { inline static bool buttonPressed(Qt::MouseButton button)
{
return buttonState(button) == InputPressed; return buttonState(button) == InputPressed;
} }
@ -124,7 +131,8 @@ namespace Qtk {
* @param button Mouse button to check state. * @param button Mouse button to check state.
* @return True if the key is in InputReleased state. * @return True if the key is in InputReleased state.
*/ */
inline static bool buttonReleased(Qt::MouseButton button) { inline static bool buttonReleased(Qt::MouseButton button)
{
return buttonState(button) == InputReleased; return buttonState(button) == InputReleased;
} }

View File

@ -21,23 +21,28 @@ Qtk::MeshRenderer::MeshManager Qtk::MeshRenderer::sInstances;
* Constructors / Destructors * Constructors / Destructors
******************************************************************************/ ******************************************************************************/
MeshRenderer::MeshRenderer( MeshRenderer::MeshRenderer(const char * name, Vertices vertices,
const char * name, Vertices vertices, Indices indices, DrawMode mode) : Indices indices, DrawMode mode) :
MeshRenderer( MeshRenderer(name, ShapeBase(mode, std::move(vertices), std::move(indices)))
name, ShapeBase(mode, std::move(vertices), std::move(indices))) {} {
}
MeshRenderer::MeshRenderer(const char * name) : MeshRenderer::MeshRenderer(const char * name) :
MeshRenderer(name, Cube(QTK_DRAW_ELEMENTS)) {} MeshRenderer(name, Cube(QTK_DRAW_ELEMENTS))
{
}
MeshRenderer::MeshRenderer(const char * name, const ShapeBase & shape) : MeshRenderer::MeshRenderer(const char * name, const ShapeBase & shape) :
Object(name, shape, QTK_MESH), mVertexShader(":/shaders/multi-color.vert"), Object(name, shape, QTK_MESH), mVertexShader(":/shaders/multi-color.vert"),
mFragmentShader(":/shaders/multi-color.frag"), mDrawType(GL_TRIANGLES) { mFragmentShader(":/shaders/multi-color.frag"), mDrawType(GL_TRIANGLES)
{
mShape = Shape(shape); mShape = Shape(shape);
init(); init();
sInstances.insert(name, this); sInstances.insert(name, this);
} }
MeshRenderer::~MeshRenderer() { MeshRenderer::~MeshRenderer()
{
sInstances.remove(mName.c_str()); sInstances.remove(mName.c_str());
} }
@ -45,14 +50,15 @@ MeshRenderer::~MeshRenderer() {
* Public Methods * Public Methods
******************************************************************************/ ******************************************************************************/
void MeshRenderer::init() { void MeshRenderer::init()
if(mVAO.isCreated()) { {
if (mVAO.isCreated()) {
mVAO.destroy(); mVAO.destroy();
} }
if(mProgram.isLinked()) { if (mProgram.isLinked()) {
mProgram.removeAllShaders(); mProgram.removeAllShaders();
} }
if(mVBO.isCreated()) { if (mVBO.isCreated()) {
mVBO.destroy(); mVBO.destroy();
} }
@ -60,10 +66,10 @@ void MeshRenderer::init() {
mVAO.bind(); mVAO.bind();
mProgram.create(); mProgram.create();
mProgram.addShaderFromSourceFile( mProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,
QOpenGLShader::Vertex, mVertexShader.c_str()); mVertexShader.c_str());
mProgram.addShaderFromSourceFile( mProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,
QOpenGLShader::Fragment, mFragmentShader.c_str()); mFragmentShader.c_str());
mProgram.link(); mProgram.link();
mProgram.bind(); mProgram.bind();
@ -84,9 +90,9 @@ void MeshRenderer::init() {
mProgram.setAttributeBuffer(0, GL_FLOAT, 0, 3, sizeof(QVector3D)); mProgram.setAttributeBuffer(0, GL_FLOAT, 0, 3, sizeof(QVector3D));
// Enable color attribute, setting offset to total size of vertices() // Enable color attribute, setting offset to total size of vertices()
mProgram.enableAttributeArray(1); mProgram.enableAttributeArray(1);
mProgram.setAttributeBuffer( mProgram.setAttributeBuffer(1, GL_FLOAT,
1, GL_FLOAT, getVertices().size() * sizeof(getVertices()[0]), 3, getVertices().size() * sizeof(getVertices()[0]),
sizeof(QVector3D)); 3, sizeof(QVector3D));
mVBO.release(); mVBO.release();
@ -94,28 +100,27 @@ void MeshRenderer::init() {
mVAO.release(); mVAO.release();
} }
void MeshRenderer::draw() { void MeshRenderer::draw()
{
bindShaders(); bindShaders();
mVAO.bind(); mVAO.bind();
if(mTexture.hasTexture()) { if (mTexture.hasTexture()) {
mTexture.getOpenGLTexture().bind(); mTexture.getOpenGLTexture().bind();
} }
// TODO: Automate uniforms some other way // TODO: Automate uniforms some other way
setUniformMVP(); setUniformMVP();
if(mShape.mDrawMode == QTK_DRAW_ARRAYS) { if (mShape.mDrawMode == QTK_DRAW_ARRAYS) {
glDrawArrays(mDrawType, 0, getVertices().size()); glDrawArrays(mDrawType, 0, getVertices().size());
} else if( } else if (mShape.mDrawMode == QTK_DRAW_ELEMENTS
mShape.mDrawMode == QTK_DRAW_ELEMENTS || mShape.mDrawMode == QTK_DRAW_ELEMENTS_NORMALS) {
|| mShape.mDrawMode == QTK_DRAW_ELEMENTS_NORMALS) { glDrawElements(mDrawType, mShape.mIndices.size(), GL_UNSIGNED_INT,
glDrawElements( mShape.mIndices.data());
mDrawType, mShape.mIndices.size(), GL_UNSIGNED_INT,
mShape.mIndices.data());
} }
if(mTexture.hasTexture()) { if (mTexture.hasTexture()) {
mTexture.getOpenGLTexture().release(); mTexture.getOpenGLTexture().release();
} }
@ -123,30 +128,33 @@ void MeshRenderer::draw() {
releaseShaders(); releaseShaders();
} }
void MeshRenderer::enableAttributeArray(int location) { void MeshRenderer::enableAttributeArray(int location)
{
ShaderBindScope lock(&mProgram, mBound); ShaderBindScope lock(&mProgram, mBound);
mVAO.bind(); mVAO.bind();
mProgram.enableAttributeArray(location); mProgram.enableAttributeArray(location);
mVAO.release(); mVAO.release();
} }
void MeshRenderer::reallocateTexCoords(const TexCoords & t, unsigned dims) { void MeshRenderer::reallocateTexCoords(const TexCoords & t, unsigned dims)
{
mVAO.bind(); mVAO.bind();
mNBO.destroy(); mNBO.destroy();
mNBO.create(); mNBO.create();
mNBO.bind(); mNBO.bind();
mNBO.allocate(t.data(), t.size() * sizeof(t[0])); mNBO.allocate(t.data(), t.size() * sizeof(t[0]));
enableAttributeArray(1); enableAttributeArray(1);
if(dims == 2) { if (dims == 2) {
setAttributeBuffer(1, GL_FLOAT, 0, 2, sizeof(QVector2D)); setAttributeBuffer(1, GL_FLOAT, 0, 2, sizeof(QVector2D));
} else if(dims == 3) { } else if (dims == 3) {
setAttributeBuffer(1, GL_FLOAT, 0, 3, sizeof(QVector3D)); setAttributeBuffer(1, GL_FLOAT, 0, 3, sizeof(QVector3D));
} }
mNBO.release(); mNBO.release();
mVAO.release(); mVAO.release();
} }
void MeshRenderer::reallocateNormals(const Normals & n, unsigned dims) { void MeshRenderer::reallocateNormals(const Normals & n, unsigned dims)
{
// TODO: Store state to track if buffer objects are bound // TODO: Store state to track if buffer objects are bound
mVAO.bind(); mVAO.bind();
mNBO.destroy(); mNBO.destroy();
@ -154,42 +162,46 @@ void MeshRenderer::reallocateNormals(const Normals & n, unsigned dims) {
mNBO.bind(); mNBO.bind();
mNBO.allocate(n.data(), n.size() * sizeof(n[0])); mNBO.allocate(n.data(), n.size() * sizeof(n[0]));
enableAttributeArray(1); enableAttributeArray(1);
if(dims == 2) { if (dims == 2) {
setAttributeBuffer(1, GL_FLOAT, 0, 2, sizeof(QVector2D)); setAttributeBuffer(1, GL_FLOAT, 0, 2, sizeof(QVector2D));
} else if(dims == 3) { } else if (dims == 3) {
setAttributeBuffer(1, GL_FLOAT, 0, 3, sizeof(QVector3D)); setAttributeBuffer(1, GL_FLOAT, 0, 3, sizeof(QVector3D));
} }
mNBO.release(); mNBO.release();
mVAO.release(); mVAO.release();
} }
void MeshRenderer::setShaders( void MeshRenderer::setShaders(const std::string & vert,
const std::string & vert, const std::string & frag) { const std::string & frag)
{
mVertexShader = vert; mVertexShader = vert;
mFragmentShader = frag; mFragmentShader = frag;
init(); init();
} }
void MeshRenderer::setUniformMVP( void MeshRenderer::setUniformMVP(const char * model, const char * view,
const char * model, const char * view, const char * projection) { const char * projection)
{
ShaderBindScope lock(&mProgram, mBound); ShaderBindScope lock(&mProgram, mBound);
mProgram.setUniformValue(projection, Scene::getProjectionMatrix()); mProgram.setUniformValue(projection, Scene::getProjectionMatrix());
mProgram.setUniformValue(view, Scene::getViewMatrix()); mProgram.setUniformValue(view, Scene::getViewMatrix());
mProgram.setUniformValue(model, mTransform.toMatrix()); mProgram.setUniformValue(model, mTransform.toMatrix());
} }
void MeshRenderer::setShape(const Shape & value) { void MeshRenderer::setShape(const Shape & value)
{
Object::setShape(value); Object::setShape(value);
init(); init();
} }
void MeshRenderer::setColor(const QVector3D & color) { void MeshRenderer::setColor(const QVector3D & color)
if(mShape.mColors.empty()) { {
for(const auto & vertex : mShape.getVertices()) { if (mShape.mColors.empty()) {
for (const auto & vertex : mShape.getVertices()) {
mShape.mColors.push_back(color); mShape.mColors.push_back(color);
} }
} else { } else {
for(int i = 0; i < mShape.getColors().size(); i++) { for (int i = 0; i < mShape.getColors().size(); i++) {
mShape.mColors[i] = color; mShape.mColors[i] = color;
} }
} }
@ -197,8 +209,9 @@ void MeshRenderer::setColor(const QVector3D & color) {
init(); init();
} }
void MeshRenderer::setAttributeBuffer( void MeshRenderer::setAttributeBuffer(int location, GLenum type, int offset,
int location, GLenum type, int offset, int tupleSize, int stride) { int tupleSize, int stride)
{
ShaderBindScope lock(&mProgram, mBound); ShaderBindScope lock(&mProgram, mBound);
mVAO.bind(); mVAO.bind();
mProgram.setAttributeBuffer(location, type, offset, tupleSize, stride); mProgram.setAttributeBuffer(location, type, offset, tupleSize, stride);
@ -210,8 +223,9 @@ void MeshRenderer::setAttributeBuffer(
******************************************************************************/ ******************************************************************************/
// 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 (!sInstances.contains(name)) {
#if QTK_DEBUG #if QTK_DEBUG
qDebug() << "Attempt to access MeshRenderer instance that does not exist! (" qDebug() << "Attempt to access MeshRenderer instance that does not exist! ("
<< qPrintable(name) << ")\n"; << qPrintable(name) << ")\n";

View File

@ -14,8 +14,10 @@
#include "qtkapi.h" #include "qtkapi.h"
#include "shape.h" #include "shape.h"
namespace Qtk { namespace Qtk
class QTKAPI MeshRenderer : public Object { {
class QTKAPI MeshRenderer : public Object
{
public: public:
/************************************************************************* /*************************************************************************
* Typedefs * Typedefs
@ -38,9 +40,8 @@ namespace Qtk {
* @param indices Indicess to use for initializes geometry shape. * @param indices Indicess to use for initializes geometry shape.
* @param mode OpenGL draw mode. Supported modes are prefixed with QTK_* * @param mode OpenGL draw mode. Supported modes are prefixed with QTK_*
*/ */
MeshRenderer( MeshRenderer(const char * name, Vertices vertices, Indices indices,
const char * name, Vertices vertices, Indices indices, DrawMode mode = QTK_DRAW_ARRAYS);
DrawMode mode = QTK_DRAW_ARRAYS);
/** /**
* Delegate constructor. * Delegate constructor.
@ -112,14 +113,16 @@ namespace Qtk {
/** /**
* @param vert Path to vertex shader to use for this MeshRenderer. * @param vert Path to vertex shader to use for this MeshRenderer.
*/ */
inline void setShaderVertex(const std::string & vert) { inline void setShaderVertex(const std::string & vert)
{
mVertexShader = vert; mVertexShader = vert;
} }
/** /**
* @param frag Path to fragment shader to use for this MeshRenderer. * @param frag Path to fragment shader to use for this MeshRenderer.
*/ */
inline void setShaderFragment(const std::string & frag) { inline void setShaderFragment(const std::string & frag)
{
mFragmentShader = frag; mFragmentShader = frag;
} }
@ -134,7 +137,8 @@ namespace Qtk {
* @param location Index location of the uniform value we are setting. * @param location Index location of the uniform value we are setting.
* @param value The value to use for the uniform. * @param value The value to use for the uniform.
*/ */
template <typename T> inline void setUniform(int location, T value) { template <typename T> inline void setUniform(int location, T value)
{
ShaderBindScope lock(&mProgram, mBound); ShaderBindScope lock(&mProgram, mBound);
mProgram.setUniformValue(location, value); mProgram.setUniformValue(location, value);
} }
@ -145,7 +149,8 @@ namespace Qtk {
* @param value The value to use for the uniform. * @param value The value to use for the uniform.
*/ */
template <typename T> template <typename T>
inline void setUniform(const char * location, T value) { inline void setUniform(const char * location, T value)
{
ShaderBindScope lock(&mProgram, mBound); ShaderBindScope lock(&mProgram, mBound);
mProgram.setUniformValue(location, value); mProgram.setUniformValue(location, value);
} }
@ -159,9 +164,9 @@ namespace Qtk {
* @param view Name of the uniform to store the View matrix. * @param view Name of the uniform to store the View matrix.
* @param projection Name of the uniform to store the Projection matrix. * @param projection Name of the uniform to store the Projection matrix.
*/ */
void setUniformMVP( void setUniformMVP(const char * model = "uModel",
const char * model = "uModel", const char * view = "uView", const char * view = "uView",
const char * projection = "uProjection"); const char * projection = "uProjection");
/** /**
* Sets the shape of the MeshRenderer using the Object base class method. * Sets the shape of the MeshRenderer using the Object base class method.
@ -192,8 +197,8 @@ namespace Qtk {
* @param stride Stride between groups of elements in the buffer. * @param stride Stride between groups of elements in the buffer.
* For example (x, y) data stride is `2 * sizeof(type)` * For example (x, y) data stride is `2 * sizeof(type)`
*/ */
void setAttributeBuffer( void setAttributeBuffer(int location, GLenum type, int offset,
int location, GLenum type, int offset, int tupleSize, int stride = 0); int tupleSize, int stride = 0);
/************************************************************************* /*************************************************************************
* Accessors * Accessors
@ -211,11 +216,13 @@ namespace Qtk {
*/ */
inline Transform3D & getTransform() { return mTransform; } inline Transform3D & getTransform() { return mTransform; }
[[nodiscard]] inline std::string getVertexShader() const override { [[nodiscard]] inline std::string getVertexShader() const override
{
return mVertexShader; return mVertexShader;
} }
[[nodiscard]] inline std::string getFragmentShader() const override { [[nodiscard]] inline std::string getFragmentShader() const override
{
return mFragmentShader; return mFragmentShader;
} }

View File

@ -21,25 +21,28 @@ Model::ModelManager Model::mManager;
* Public Member Functions * Public Member Functions
******************************************************************************/ ******************************************************************************/
void Model::draw() { void Model::draw()
for(auto & mesh : mMeshes) { {
for (auto & mesh : mMeshes) {
mesh.mTransform = mTransform; mesh.mTransform = mTransform;
mesh.draw(); mesh.draw();
} }
} }
void Model::draw(QOpenGLShaderProgram & shader) { void Model::draw(QOpenGLShaderProgram & shader)
for(auto & mesh : mMeshes) { {
for (auto & mesh : mMeshes) {
mesh.mTransform = mTransform; mesh.mTransform = mTransform;
mesh.draw(shader); mesh.draw(shader);
} }
} }
void Model::flipTexture(const std::string & fileName, bool flipX, bool flipY) { void Model::flipTexture(const std::string & fileName, bool flipX, bool flipY)
{
bool modified = false; bool modified = false;
std::string fullPath = mDirectory + '/' + fileName; std::string fullPath = mDirectory + '/' + fileName;
for(auto & texture : mTexturesLoaded) { for (auto & texture : mTexturesLoaded) {
if(texture.mPath == fileName) { if (texture.mPath == fileName) {
texture.mTexture->destroy(); texture.mTexture->destroy();
texture.mTexture->create(); texture.mTexture->create();
texture.mTexture->setData( texture.mTexture->setData(
@ -47,14 +50,15 @@ void Model::flipTexture(const std::string & fileName, bool flipX, bool flipY) {
modified = true; modified = true;
} }
} }
if(!modified) { if (!modified) {
qDebug() << "Attempt to flip texture that doesn't exist: " qDebug() << "Attempt to flip texture that doesn't exist: "
<< fullPath.c_str() << "\n"; << fullPath.c_str() << "\n";
} }
} }
// Static function to access ModelManager for getting Models by name // Static function to access ModelManager for getting Models by name
Model * Qtk::Model::getInstance(const char * name) { Model * Qtk::Model::getInstance(const char * name)
{
return mManager[name]; return mManager[name];
} }
@ -62,10 +66,11 @@ Model * Qtk::Model::getInstance(const char * name) {
* Private Member Functions * Private Member Functions
******************************************************************************/ ******************************************************************************/
void Model::loadModel(const std::string & path) { void Model::loadModel(const std::string & path)
{
Assimp::Importer import; Assimp::Importer import;
// If using a Qt Resource path, use QtkIOSystem for file handling. // If using a Qt Resource path, use QtkIOSystem for file handling.
if(path.front() == ':') { if (path.front() == ':') {
import.SetIOHandler(new QtkIOSystem()); import.SetIOHandler(new QtkIOSystem());
} }
// Used as base path for loading model textures. // Used as base path for loading model textures.
@ -81,7 +86,8 @@ void Model::loadModel(const std::string & path) {
| aiProcess_SplitLargeMeshes); | aiProcess_SplitLargeMeshes);
// If there were errors, print and return // If there were errors, print and return
if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) { if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE
|| !scene->mRootNode) {
qDebug() << "Error::ASSIMP::" << import.GetErrorString() << "\n"; qDebug() << "Error::ASSIMP::" << import.GetErrorString() << "\n";
return; return;
} }
@ -99,26 +105,28 @@ void Model::loadModel(const std::string & path) {
mManager.insert(getName().c_str(), this); mManager.insert(getName().c_str(), this);
} }
void Model::processNode(aiNode * node, const aiScene * scene) { void Model::processNode(aiNode * node, const aiScene * scene)
{
// Process each mesh that is available for this node // Process each mesh that is available for this node
for(GLuint i = 0; i < node->mNumMeshes; i++) { for (GLuint i = 0; i < node->mNumMeshes; i++) {
aiMesh * mesh = scene->mMeshes[node->mMeshes[i]]; aiMesh * mesh = scene->mMeshes[node->mMeshes[i]];
mMeshes.push_back(processMesh(mesh, scene)); mMeshes.push_back(processMesh(mesh, scene));
} }
// Process each child node for this mesh using recursion // Process each child node for this mesh using recursion
for(GLuint i = 0; i < node->mNumChildren; i++) { for (GLuint i = 0; i < node->mNumChildren; i++) {
processNode(node->mChildren[i], scene); processNode(node->mChildren[i], scene);
} }
} }
ModelMesh Model::processMesh(aiMesh * mesh, const aiScene * scene) { ModelMesh Model::processMesh(aiMesh * mesh, const aiScene * scene)
{
ModelMesh::Vertices vertices; ModelMesh::Vertices vertices;
ModelMesh::Indices indices; ModelMesh::Indices indices;
ModelMesh::Textures textures; ModelMesh::Textures textures;
// For each vertex in the aiMesh // For each vertex in the aiMesh
for(GLuint i = 0; i < mesh->mNumVertices; i++) { for (GLuint i = 0; i < mesh->mNumVertices; i++) {
// Create a local vertex object for positions, normals, and texture coords // Create a local vertex object for positions, normals, and texture coords
ModelVertex vertex; ModelVertex vertex;
@ -132,7 +140,7 @@ ModelMesh Model::processMesh(aiMesh * mesh, const aiScene * scene) {
// Set the position of our local vertex to the local vector object // Set the position of our local vertex to the local vector object
vertex.mPosition = vector3D; vertex.mPosition = vector3D;
if(mesh->HasNormals()) { if (mesh->HasNormals()) {
// Initialize vertex normal // Initialize vertex normal
vector3D.setX(mesh->mNormals[i].x); vector3D.setX(mesh->mNormals[i].x);
vector3D.setY(mesh->mNormals[i].y); vector3D.setY(mesh->mNormals[i].y);
@ -142,7 +150,7 @@ ModelMesh Model::processMesh(aiMesh * mesh, const aiScene * scene) {
} }
// Initialize texture coordinates, if any are available // Initialize texture coordinates, if any are available
if(mesh->mTextureCoords[0]) { if (mesh->mTextureCoords[0]) {
QVector2D vector2D; QVector2D vector2D;
// Texture coordinates // Texture coordinates
vector2D.setX(mesh->mTextureCoords[0][i].x); vector2D.setX(mesh->mTextureCoords[0][i].x);
@ -169,16 +177,16 @@ ModelMesh Model::processMesh(aiMesh * mesh, const aiScene * scene) {
} }
// For each face on the mesh, process its indices // For each face on the mesh, process its indices
for(GLuint i = 0; i < mesh->mNumFaces; i++) { for (GLuint i = 0; i < mesh->mNumFaces; i++) {
aiFace face = mesh->mFaces[i]; aiFace face = mesh->mFaces[i];
for(GLuint j = 0; j < face.mNumIndices; j++) { for (GLuint j = 0; j < face.mNumIndices; j++) {
// Add the index to out container of indices // Add the index to out container of indices
indices.push_back(face.mIndices[j]); indices.push_back(face.mIndices[j]);
} }
} }
// Process material // Process material
if(mesh->mMaterialIndex >= 0) { if (mesh->mMaterialIndex >= 0) {
// Get the material attached to the model using Assimp // Get the material attached to the model using Assimp
aiMaterial * material = scene->mMaterials[mesh->mMaterialIndex]; aiMaterial * material = scene->mMaterials[mesh->mMaterialIndex];
// Get all diffuse textures from the material // Get all diffuse textures from the material
@ -200,25 +208,26 @@ ModelMesh Model::processMesh(aiMesh * mesh, const aiScene * scene) {
textures.insert(textures.end(), normalMaps.begin(), normalMaps.end()); textures.insert(textures.end(), normalMaps.begin(), normalMaps.end());
} }
return { return {vertices, indices, textures, mVertexShader.c_str(),
vertices, indices, textures, mVertexShader.c_str(), mFragmentShader.c_str()};
mFragmentShader.c_str()};
} }
ModelMesh::Textures Model::loadMaterialTextures( ModelMesh::Textures Model::loadMaterialTextures(aiMaterial * mat,
aiMaterial * mat, aiTextureType type, const std::string & typeName) { aiTextureType type,
const std::string & typeName)
{
ModelMesh::Textures textures; ModelMesh::Textures textures;
for(GLuint i = 0; i < mat->GetTextureCount(type); i++) { for (GLuint i = 0; i < mat->GetTextureCount(type); i++) {
// Call GetTexture to get the name of the texture file to load // Call GetTexture to get the name of the texture file to load
aiString fileName; aiString fileName;
mat->GetTexture(type, i, &fileName); mat->GetTexture(type, i, &fileName);
// Check if we have already loaded this texture // Check if we have already loaded this texture
bool skip = false; bool skip = false;
for(auto & j : mTexturesLoaded) { for (auto & j : mTexturesLoaded) {
// If the path to the texture already exists in m_texturesLoaded, skip it // If the path to the texture already exists in m_texturesLoaded, skip it
if(std::strcmp(j.mPath.data(), fileName.C_Str()) == 0) { if (std::strcmp(j.mPath.data(), fileName.C_Str()) == 0) {
textures.push_back(j); textures.push_back(j);
// If we have loaded the texture, do not load it again // If we have loaded the texture, do not load it again
skip = true; skip = true;
@ -227,7 +236,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::initTexture( texture.mTexture = OpenGLTextureFactory::initTexture(
std::string(mDirectory + '/' + fileName.C_Str()).c_str(), false, std::string(mDirectory + '/' + fileName.C_Str()).c_str(), false,
@ -246,7 +255,8 @@ ModelMesh::Textures Model::loadMaterialTextures(
return textures; return textures;
} }
void Model::sortModelMeshes() { void Model::sortModelMeshes()
{
auto cameraPos = Scene::getCamera().getTransform(); 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

View File

@ -24,12 +24,14 @@
#include "modelmesh.h" #include "modelmesh.h"
#include "qtkapi.h" #include "qtkapi.h"
namespace Qtk { namespace Qtk
{
/** /**
* Model object that has a ModelMesh. * Model object that has a ModelMesh.
* Top-level object that represents 3D models stored within a scene. * Top-level object that represents 3D models stored within a scene.
*/ */
class QTKAPI Model : public Object { class QTKAPI Model : public Object
{
public: public:
/************************************************************************* /*************************************************************************
* Typedefs * Typedefs
@ -51,13 +53,12 @@ namespace Qtk {
* @param vertexShader Optional path to custom vertex shader. * @param vertexShader Optional path to custom vertex shader.
* @param fragmentShader Optional path to custom fragment shader. * @param fragmentShader Optional path to custom fragment shader.
*/ */
inline Model( inline Model(const char * name, const char * path,
const char * name, const char * path, const char * vertexShader = ":/shaders/model-basic.vert",
const char * vertexShader = ":/shaders/model-basic.vert", const char * fragmentShader = ":/shaders/model-basic.frag") :
const char * fragmentShader = ":/shaders/model-basic.frag") : Object(name, QTK_MODEL), mModelPath(path),
Object(name, QTK_MODEL), mVertexShader(vertexShader), mFragmentShader(fragmentShader)
mModelPath(path), mVertexShader(vertexShader), {
mFragmentShader(fragmentShader) {
loadModel(mModelPath); loadModel(mModelPath);
} }
@ -86,8 +87,8 @@ namespace Qtk {
* @param flipX Flip the texture along the X axis * @param flipX Flip the texture along the X axis
* @param flipY Flip the texture along the Y axis * @param flipY Flip the texture along the Y axis
*/ */
void flipTexture( void flipTexture(const std::string & fileName, bool flipX = false,
const std::string & fileName, bool flipX = false, bool flipY = true); bool flipY = true);
/************************************************************************* /*************************************************************************
* Setters * Setters
@ -101,8 +102,9 @@ namespace Qtk {
* @param value The value to assign to the uniform * @param value The value to assign to the uniform
*/ */
template <typename T> template <typename T>
inline void setUniform(const char * location, T value) { inline 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();
@ -127,11 +129,13 @@ namespace Qtk {
*/ */
inline Transform3D & getTransform() { return mTransform; } inline Transform3D & getTransform() { return mTransform; }
[[nodiscard]] inline std::string getVertexShader() const override { [[nodiscard]] inline std::string getVertexShader() const override
{
return mVertexShader; return mVertexShader;
} }
[[nodiscard]] inline std::string getFragmentShader() const override { [[nodiscard]] inline std::string getFragmentShader() const override
{
return mFragmentShader; return mFragmentShader;
} }
@ -183,8 +187,9 @@ namespace Qtk {
* @param typeName Texture type name in string format. * @param typeName Texture type name in string format.
* @return Collection of all textures for a single ModelMesh. * @return Collection of all textures for a single ModelMesh.
*/ */
ModelMesh::Textures loadMaterialTextures( ModelMesh::Textures loadMaterialTextures(aiMaterial * mat,
aiMaterial * mat, aiTextureType type, const std::string & typeName); aiTextureType type,
const std::string & typeName);
/** /**
* Sorts each mesh in the Model based on distance from the camera. * Sorts each mesh in the Model based on distance from the camera.

View File

@ -15,7 +15,8 @@ using namespace Qtk;
* Public Member Functions * Public Member Functions
******************************************************************************/ ******************************************************************************/
void ModelMesh::draw(QOpenGLShaderProgram & shader) { void ModelMesh::draw(QOpenGLShaderProgram & shader)
{
mVAO->bind(); mVAO->bind();
// Bind shader // Bind shader
shader.bind(); shader.bind();
@ -28,7 +29,7 @@ void ModelMesh::draw(QOpenGLShaderProgram & shader) {
GLuint diffuseCount = 1; GLuint diffuseCount = 1;
GLuint specularCount = 1; GLuint specularCount = 1;
GLuint normalCount = 1; GLuint normalCount = 1;
for(GLuint i = 0; i < mTextures.size(); i++) { for (GLuint i = 0; i < mTextures.size(); i++) {
// Activate the current texture index by adding offset to GL_TEXTURE0 // Activate the current texture index by adding offset to GL_TEXTURE0
glActiveTexture(GL_TEXTURE0 + i); glActiveTexture(GL_TEXTURE0 + i);
mTextures[i].mTexture->bind(); mTextures[i].mTexture->bind();
@ -38,13 +39,13 @@ void ModelMesh::draw(QOpenGLShaderProgram & shader) {
// Specular: material.texture_specular1, material.texture_specular2, ... // Specular: material.texture_specular1, material.texture_specular2, ...
std::string number; std::string number;
std::string name = mTextures[i].mType; std::string name = mTextures[i].mType;
if(name == "texture_diffuse") { if (name == "texture_diffuse") {
number = std::to_string(diffuseCount++); number = std::to_string(diffuseCount++);
} }
if(name == "texture_specular") { if (name == "texture_specular") {
number = std::to_string(specularCount++); number = std::to_string(specularCount++);
} }
if(name == "texture_normal") { if (name == "texture_normal") {
number = std::to_string(normalCount++); number = std::to_string(normalCount++);
} }
@ -57,11 +58,11 @@ void ModelMesh::draw(QOpenGLShaderProgram & shader) {
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
// Draw the mesh // Draw the mesh
glDrawElements( glDrawElements(GL_TRIANGLES, mIndices.size(), GL_UNSIGNED_INT,
GL_TRIANGLES, mIndices.size(), GL_UNSIGNED_INT, mIndices.data()); mIndices.data());
// Release shader, textures // Release shader, textures
for(const auto & texture : mTextures) { for (const auto & texture : mTextures) {
texture.mTexture->release(); texture.mTexture->release();
} }
shader.release(); shader.release();
@ -72,7 +73,8 @@ void ModelMesh::draw(QOpenGLShaderProgram & shader) {
* Private Member Functions * Private Member Functions
******************************************************************************/ ******************************************************************************/
void ModelMesh::initMesh(const char * vert, const char * frag) { void ModelMesh::initMesh(const char * vert, const char * frag)
{
initializeOpenGLFunctions(); initializeOpenGLFunctions();
// Create VAO, VBO, EBO // Create VAO, VBO, EBO
@ -102,29 +104,29 @@ void ModelMesh::initMesh(const char * vert, const char * frag) {
// Positions // Positions
mProgram->enableAttributeArray(0); mProgram->enableAttributeArray(0);
mProgram->setAttributeBuffer( mProgram->setAttributeBuffer(0, GL_FLOAT, offsetof(ModelVertex, mPosition), 3,
0, GL_FLOAT, offsetof(ModelVertex, mPosition), 3, sizeof(ModelVertex)); sizeof(ModelVertex));
// Normals // Normals
mProgram->enableAttributeArray(1); mProgram->enableAttributeArray(1);
mProgram->setAttributeBuffer( mProgram->setAttributeBuffer(1, GL_FLOAT, offsetof(ModelVertex, mNormal), 3,
1, GL_FLOAT, offsetof(ModelVertex, mNormal), 3, sizeof(ModelVertex)); sizeof(ModelVertex));
// Texture Coordinates // Texture Coordinates
mProgram->enableAttributeArray(2); mProgram->enableAttributeArray(2);
mProgram->setAttributeBuffer( mProgram->setAttributeBuffer(2, GL_FLOAT,
2, GL_FLOAT, offsetof(ModelVertex, mTextureCoord), 2, offsetof(ModelVertex, mTextureCoord), 2,
sizeof(ModelVertex)); sizeof(ModelVertex));
// Vertex tangents // Vertex tangents
mProgram->enableAttributeArray(3); mProgram->enableAttributeArray(3);
mProgram->setAttributeBuffer( mProgram->setAttributeBuffer(3, GL_FLOAT, offsetof(ModelVertex, mTangent), 3,
3, GL_FLOAT, offsetof(ModelVertex, mTangent), 3, sizeof(ModelVertex)); sizeof(ModelVertex));
// Vertex bitangents // Vertex bitangents
mProgram->enableAttributeArray(4); mProgram->enableAttributeArray(4);
mProgram->setAttributeBuffer( mProgram->setAttributeBuffer(4, GL_FLOAT, offsetof(ModelVertex, mBitangent),
4, GL_FLOAT, offsetof(ModelVertex, mBitangent), 3, sizeof(ModelVertex)); 3, sizeof(ModelVertex));
mProgram->release(); mProgram->release();
mVBO->release(); mVBO->release();

View File

@ -16,7 +16,8 @@
#include "object.h" #include "object.h"
#include "transform3D.h" #include "transform3D.h"
namespace Qtk { namespace Qtk
{
/** /**
* 3D models will store this data for each vertex in geometry. * 3D models will store this data for each vertex in geometry.
*/ */
@ -41,8 +42,9 @@ namespace Qtk {
* @param type Type of texture in string format. * @param type Type of texture in string format.
* @param path Path to the texture on disk. * @param path Path to the texture on disk.
*/ */
ModelTexture(std::string type, const std::string & path) : ModelTexture(std::string type, const std::string & path) :
mType(std::move(type)), mPath(path) { mType(std::move(type)), mPath(path)
{
mTexture = OpenGLTextureFactory::initTexture(path.c_str()); mTexture = OpenGLTextureFactory::initTexture(path.c_str());
mID = mTexture->textureId(); mID = mTexture->textureId();
} }
@ -66,7 +68,8 @@ namespace Qtk {
* Mesh class specialized for storing 3D model data. * Mesh class specialized for storing 3D model data.
* Eventually this can be consolidated into a more generic class. * Eventually this can be consolidated into a more generic class.
*/ */
class QTKAPI ModelMesh : protected QOpenGLFunctions { class QTKAPI ModelMesh : protected QOpenGLFunctions
{
public: public:
/************************************************************************* /*************************************************************************
* Typedefs * Typedefs
@ -91,16 +94,16 @@ namespace Qtk {
* @param vertexShader Path to vertex shader for this ModelMesh. * @param vertexShader Path to vertex shader for this ModelMesh.
* @param fragmentShader Path to fragment shader for this ModelMesh. * @param fragmentShader Path to fragment shader for this ModelMesh.
*/ */
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", const char * fragmentShader = ":/model-basic.frag") :
const char * fragmentShader = ":/model-basic.frag") :
mProgram(new QOpenGLShaderProgram), mProgram(new QOpenGLShaderProgram),
mVAO(new QOpenGLVertexArrayObject), mVAO(new QOpenGLVertexArrayObject),
mVBO(new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer)), mVBO(new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer)),
mEBO(new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer)), mEBO(new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer)),
mVertices(std::move(vertices)), mIndices(std::move(indices)), mVertices(std::move(vertices)), mIndices(std::move(indices)),
mTextures(std::move(textures)) { mTextures(std::move(textures))
{
initMesh(vertexShader, fragmentShader); initMesh(vertexShader, fragmentShader);
} }

View File

@ -17,14 +17,16 @@
#include "shape.h" #include "shape.h"
#include "texture.h" #include "texture.h"
namespace Qtk { namespace Qtk
{
class Model; class Model;
/** /**
* Object base class for objects that can exist within a scene. * Object base class for objects that can exist within a scene.
* An object could be a Cube, Skybox, 3D Model, or other standalone entities. * 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:
@ -47,7 +49,8 @@ namespace Qtk {
// Initialize an object with no shape data assigned // Initialize an object with no shape data assigned
explicit Object(const char * name, Type type) : explicit Object(const char * name, Type type) :
mName(name), mVBO(QOpenGLBuffer::VertexBuffer), mBound(false), mName(name), mVBO(QOpenGLBuffer::VertexBuffer), mBound(false),
mType(type) { mType(type)
{
initResources(); initResources();
setObjectName(name); setObjectName(name);
} }
@ -55,7 +58,8 @@ namespace Qtk {
// Initialize an object with shape data assigned // Initialize an object with shape data assigned
Object(const char * name, const ShapeBase & shape, Type type) : Object(const char * name, const ShapeBase & shape, Type type) :
mName(name), mVBO(QOpenGLBuffer::VertexBuffer), mShape(shape), mName(name), mVBO(QOpenGLBuffer::VertexBuffer), mShape(shape),
mBound(false), mType(type) { mBound(false), mType(type)
{
initResources(); initResources();
setObjectName(name); setObjectName(name);
} }
@ -66,29 +70,35 @@ namespace Qtk {
* Accessors * Accessors
************************************************************************/ ************************************************************************/
[[nodiscard]] inline const Colors & getColors() const { [[nodiscard]] inline const Colors & getColors() const
{
return mShape.mColors; return mShape.mColors;
} }
[[nodiscard]] inline const Indices & getIndexData() const { [[nodiscard]] inline const Indices & getIndexData() const
{
return mShape.mIndices; return mShape.mIndices;
} }
[[nodiscard]] inline const Normals & getNormals() const { [[nodiscard]] inline const Normals & getNormals() const
{
return mShape.mNormals; return mShape.mNormals;
} }
[[nodiscard]] inline const Shape & getShape() const { return mShape; } [[nodiscard]] inline const Shape & getShape() const { return mShape; }
[[nodiscard]] inline const TexCoords & getTexCoords() const { [[nodiscard]] inline const TexCoords & getTexCoords() const
{
return mShape.mTexCoords; return mShape.mTexCoords;
} }
[[nodiscard]] inline const Texture & getTexture() const { [[nodiscard]] inline const Texture & getTexture() const
{
return mTexture; return mTexture;
} }
[[nodiscard]] inline const Vertices & getVertices() const { [[nodiscard]] inline const Vertices & getVertices() const
{
return mShape.mVertices; return mShape.mVertices;
} }
@ -96,15 +106,18 @@ namespace Qtk {
[[nodiscard]] inline const Type & getType() const { return mType; } [[nodiscard]] inline const Type & getType() const { return mType; }
[[nodiscard]] inline virtual const Transform3D & getTransform() const { [[nodiscard]] inline virtual const Transform3D & getTransform() const
{
return mTransform; return mTransform;
} }
[[nodiscard]] inline virtual std::string getVertexShader() const { [[nodiscard]] inline virtual std::string getVertexShader() const
{
return "Base Object has no vertex shader."; return "Base Object has no vertex shader.";
} }
[[nodiscard]] virtual inline std::string getFragmentShader() const { [[nodiscard]] virtual inline std::string getFragmentShader() const
{
return "Base Object has no fragment shader."; return "Base Object has no fragment shader.";
} }
@ -114,84 +127,97 @@ namespace Qtk {
virtual inline void setName(const std::string & name) { mName = name; } virtual inline void setName(const std::string & name) { mName = name; }
virtual inline void setColors(const Colors & value) { virtual inline void setColors(const Colors & value)
{
mShape.mColors = value; mShape.mColors = value;
} }
virtual inline void setIndices(const Indices & value) { virtual inline void setIndices(const Indices & value)
{
mShape.mIndices = value; mShape.mIndices = value;
} }
virtual inline void setNormals(const Normals & value) { virtual inline void setNormals(const Normals & value)
{
mShape.mNormals = value; mShape.mNormals = value;
} }
virtual inline void setShape(const Shape & value) { mShape = value; } virtual inline void setShape(const Shape & value) { mShape = value; }
virtual inline void setTexCoords(const TexCoords & value) { virtual inline void setTexCoords(const TexCoords & value)
{
mShape.mTexCoords = value; mShape.mTexCoords = value;
} }
virtual inline void setTexture( virtual inline void setTexture(const char * path, bool flipX = false,
const char * path, bool flipX = false, bool flipY = false) { bool flipY = false)
{
mTexture.setTexture(path, flipX, flipY); mTexture.setTexture(path, flipX, flipY);
} }
virtual inline void setCubeMap(const char * path) { virtual inline void setCubeMap(const char * path)
{
mTexture.setCubeMap(path); mTexture.setCubeMap(path);
} }
virtual inline void setTexture(const Texture & t) { virtual inline void setTexture(const Texture & t)
{
mTexture.setTexture(t.getPath()); mTexture.setTexture(t.getPath());
} }
virtual inline void setVertices(const Vertices & value) { virtual inline void setVertices(const Vertices & value)
{
mShape.mVertices = value; mShape.mVertices = value;
} }
inline void setScaleX(double x) { inline void setScaleX(double x)
mTransform.setScale( {
x, mTransform.getScale().y(), mTransform.getScale().z()); mTransform.setScale(x, mTransform.getScale().y(),
mTransform.getScale().z());
} }
inline void setScaleY(double y) { inline void setScaleY(double y)
mTransform.setScale( {
mTransform.getScale().x(), y, mTransform.getScale().z()); mTransform.setScale(mTransform.getScale().x(), y,
mTransform.getScale().z());
} }
inline void setScaleZ(double z) { inline void setScaleZ(double z)
mTransform.setScale( {
mTransform.getScale().x(), mTransform.getScale().y(), z); mTransform.setScale(mTransform.getScale().x(),
mTransform.getScale().y(), z);
} }
inline void setTranslationX(double x) { inline void setTranslationX(double x)
mTransform.setTranslation( {
x, mTransform.getTranslation().y(), mTransform.setTranslation(x, mTransform.getTranslation().y(),
mTransform.getTranslation().z()); mTransform.getTranslation().z());
} }
inline void setTranslationY(double y) { inline void setTranslationY(double y)
mTransform.setTranslation( {
mTransform.getTranslation().x(), y, mTransform.setTranslation(mTransform.getTranslation().x(), y,
mTransform.getTranslation().z()); mTransform.getTranslation().z());
} }
inline void setTranslationZ(double z) { inline void setTranslationZ(double z)
mTransform.setTranslation( {
mTransform.getTranslation().x(), mTransform.getTranslation().y(), mTransform.setTranslation(mTransform.getTranslation().x(),
z); mTransform.getTranslation().y(), z);
} }
/************************************************************************* /*************************************************************************
* Public Methods * Public Methods
************************************************************************/ ************************************************************************/
virtual inline void bindShaders() { virtual inline void bindShaders()
{
mBound = true; mBound = true;
mProgram.bind(); mProgram.bind();
} }
virtual inline void releaseShaders() { virtual inline void releaseShaders()
{
mBound = false; mBound = false;
mProgram.release(); mProgram.release();
} }

View File

@ -27,11 +27,13 @@
* This cannot be defined within any namespace, but can be called by ctors. * This cannot be defined within any namespace, but can be called by ctors.
* See object.h for example. * See object.h for example.
*/ */
inline void initResources() { inline void initResources()
{
Q_INIT_RESOURCE(resources); Q_INIT_RESOURCE(resources);
} }
namespace Qtk { namespace Qtk
{
/** /**
* Flag to set context for debug messages. * Flag to set context for debug messages.
*/ */
@ -43,9 +45,10 @@ namespace Qtk {
* @param widget Widget to start the search from. * @param widget Widget to start the search from.
* @return Top level parent widget or Q_NULLPTR if no parent * @return Top level parent widget or Q_NULLPTR if no parent
*/ */
static QWidget * topLevelParent(QWidget * widget) { static QWidget * topLevelParent(QWidget * widget)
{
QString name = widget->objectName(); QString name = widget->objectName();
while(widget->parentWidget() != Q_NULLPTR) { while (widget->parentWidget() != Q_NULLPTR) {
widget = widget->parentWidget(); widget = widget->parentWidget();
} }
return widget; return widget;
@ -54,7 +57,8 @@ namespace Qtk {
/** /**
* @return Default icon to use for Qtk desktop application. * @return Default icon to use for Qtk desktop application.
*/ */
static QIcon getIcon() { static QIcon getIcon()
{
return QIcon(":/icons/icon.png"); return QIcon(":/icons/icon.png");
} }
} // namespace Qtk } // namespace Qtk

View File

@ -14,23 +14,23 @@ using namespace Qtk;
* Constructors, Destructors * Constructors, Destructors
******************************************************************************/ ******************************************************************************/
QtkIOStream::QtkIOStream(const char * pFile, const char * pMode) : QtkIOStream::QtkIOStream(const char * pFile, const char * pMode) : mFile(pFile)
mFile(pFile) { {
QString mode(pMode); QString mode(pMode);
bool open = false; bool open = false;
if(mode == "w" || mode == "wb") { if (mode == "w" || mode == "wb") {
open = mFile.open(QIODeviceBase::WriteOnly); open = mFile.open(QIODeviceBase::WriteOnly);
} else if(mode == "r" || mode == "rb") { } else if (mode == "r" || mode == "rb") {
open = mFile.open(QIODeviceBase::ReadOnly); open = mFile.open(QIODeviceBase::ReadOnly);
} else if(mode == "wt") { } else if (mode == "wt") {
open = mFile.open(QIODeviceBase::WriteOnly | QIODeviceBase::Text); open = mFile.open(QIODeviceBase::WriteOnly | QIODeviceBase::Text);
} else if(mode == "rt") { } else if (mode == "rt") {
open = mFile.open(QIODeviceBase::ReadOnly | QIODeviceBase::Text); open = mFile.open(QIODeviceBase::ReadOnly | QIODeviceBase::Text);
} else { } else {
open = false; open = false;
qDebug() << "[Qtk::QtkIOStream] Invalid file open mode: " << mode << "\n"; qDebug() << "[Qtk::QtkIOStream] Invalid file open mode: " << mode << "\n";
} }
if(!open) { if (!open) {
qDebug() << "[Qtk::QtkIOStream] Could not open file: " << QString(pFile) qDebug() << "[Qtk::QtkIOStream] Could not open file: " << QString(pFile)
<< "\n"; << "\n";
} }
@ -40,9 +40,10 @@ QtkIOStream::QtkIOStream(const char * pFile, const char * pMode) :
* Public Member Functions * Public Member Functions
******************************************************************************/ ******************************************************************************/
size_t QtkIOStream::Read(void * pvBuffer, size_t pSize, size_t pCount) { size_t QtkIOStream::Read(void * pvBuffer, size_t pSize, size_t pCount)
{
qint64 readSize = mFile.read((char *)pvBuffer, pSize * pCount); qint64 readSize = mFile.read((char *)pvBuffer, pSize * pCount);
if(readSize < 0) { if (readSize < 0) {
qDebug() << "[Qtk::QtkIOStream] Failed to read (" << pSize qDebug() << "[Qtk::QtkIOStream] Failed to read (" << pSize
<< ") bytes from file at: " << mFile.filesystemFileName().c_str() << ") bytes from file at: " << mFile.filesystemFileName().c_str()
<< "\n"; << "\n";
@ -51,9 +52,10 @@ size_t QtkIOStream::Read(void * pvBuffer, size_t pSize, size_t pCount) {
return readSize; return readSize;
} }
size_t QtkIOStream::Write(const void * pvBuffer, size_t pSize, size_t pCount) { size_t QtkIOStream::Write(const void * pvBuffer, size_t pSize, size_t pCount)
{
qint64 writeSize = mFile.write((char *)pvBuffer, pSize * pCount); qint64 writeSize = mFile.write((char *)pvBuffer, pSize * pCount);
if(writeSize < 0) { if (writeSize < 0) {
qDebug() << "[Qtk::QtkIOStream] Failed to write buffer with size (" << pSize qDebug() << "[Qtk::QtkIOStream] Failed to write buffer with size (" << pSize
<< ") to file at: " << mFile.filesystemFileName().c_str() << "\n"; << ") to file at: " << mFile.filesystemFileName().c_str() << "\n";
return -1; return -1;
@ -61,18 +63,22 @@ size_t QtkIOStream::Write(const void * pvBuffer, size_t pSize, size_t pCount) {
return writeSize; return writeSize;
} }
aiReturn QtkIOStream::Seek(size_t pOffset, aiOrigin pOrigin) { aiReturn QtkIOStream::Seek(size_t pOffset, aiOrigin pOrigin)
{
return mFile.seek(pOffset) ? aiReturn_SUCCESS : aiReturn_FAILURE; return mFile.seek(pOffset) ? aiReturn_SUCCESS : aiReturn_FAILURE;
} }
size_t QtkIOStream::Tell() const { size_t QtkIOStream::Tell() const
{
return mFile.pos(); return mFile.pos();
} }
size_t QtkIOStream::FileSize() const { size_t QtkIOStream::FileSize() const
{
return mFile.size(); return mFile.size();
} }
void QtkIOStream::Flush() { void QtkIOStream::Flush()
{
mFile.flush(); mFile.flush();
} }

View File

@ -15,12 +15,14 @@
#ifndef QTK_QTKIOSTREAM_H #ifndef QTK_QTKIOSTREAM_H
#define QTK_QTKIOSTREAM_H #define QTK_QTKIOSTREAM_H
namespace Qtk { namespace Qtk
{
/** /**
* Custom Assimp IO stream to support QtkIOSystem file handling. * Custom Assimp IO stream to support QtkIOSystem file handling.
* Allows direct use of Qt Resource paths for loading models in Assimp. * Allows direct use of Qt Resource paths for loading models in Assimp.
*/ */
class QtkIOStream : public Assimp::IOStream { class QtkIOStream : public Assimp::IOStream
{
friend class QtkIOSystem; friend class QtkIOSystem;
protected: protected:

View File

@ -15,22 +15,26 @@ using namespace Qtk;
* Public Member Functions * Public Member Functions
******************************************************************************/ ******************************************************************************/
bool QtkIOSystem::Exists(const char * pFile) const { bool QtkIOSystem::Exists(const char * pFile) const
{
return QFileInfo::exists(pFile); return QFileInfo::exists(pFile);
} }
char QtkIOSystem::getOsSeparator() const { char QtkIOSystem::getOsSeparator() const
{
return QDir::separator().toLatin1(); return QDir::separator().toLatin1();
} }
Assimp::IOStream * QtkIOSystem::Open(const char * pFile, const char * pMode) { Assimp::IOStream * QtkIOSystem::Open(const char * pFile, const char * pMode)
if(!Exists(pFile)) { {
if (!Exists(pFile)) {
qDebug() << "[Qtk::QtkIOSystem] failed to open file: " << pFile << "\n"; qDebug() << "[Qtk::QtkIOSystem] failed to open file: " << pFile << "\n";
return nullptr; return nullptr;
} }
return new QtkIOStream(pFile, pMode); return new QtkIOStream(pFile, pMode);
} }
void QtkIOSystem::Close(Assimp::IOStream * pFile) { void QtkIOSystem::Close(Assimp::IOStream * pFile)
{
delete pFile; delete pFile;
} }

View File

@ -15,11 +15,13 @@
#ifndef QTK_QTKIOSYSTEM_H #ifndef QTK_QTKIOSYSTEM_H
#define QTK_QTKIOSYSTEM_H #define QTK_QTKIOSYSTEM_H
namespace Qtk { namespace Qtk
{
/** /**
* Assimp IO system for loading models with assimp, using Qt Resource paths. * Assimp IO system for loading models with assimp, using Qt Resource paths.
*/ */
class QtkIOSystem : public Assimp::IOSystem { class QtkIOSystem : public Assimp::IOSystem
{
public: public:
QtkIOSystem() = default; QtkIOSystem() = default;
~QtkIOSystem() = default; ~QtkIOSystem() = default;
@ -40,8 +42,8 @@ namespace Qtk {
* @param pMode Mode to open file. See `man fopen`. * @param pMode Mode to open file. See `man fopen`.
* @return QtkIOStream for the opened file. * @return QtkIOStream for the opened file.
*/ */
Assimp::IOStream * Open( Assimp::IOStream * Open(const char * pFile,
const char * pFile, const char * pMode = "rb") override; const char * pMode = "rb") override;
/** /**
* @param pFile File to close. * @param pFile File to close.

View File

@ -18,16 +18,18 @@ QMatrix4x4 Scene::mProjection;
* Constructors / Destructors * Constructors / Destructors
******************************************************************************/ ******************************************************************************/
Scene::Scene() : mSceneName("Default Scene") { Scene::Scene() : mSceneName("Default Scene")
{
mCamera.getTransform().setTranslation(0.0f, 0.0f, 20.0f); mCamera.getTransform().setTranslation(0.0f, 0.0f, 20.0f);
mCamera.getTransform().setRotation(-5.0f, 0.0f, 1.0f, 0.0f); mCamera.getTransform().setRotation(-5.0f, 0.0f, 1.0f, 0.0f);
} }
Scene::~Scene() { Scene::~Scene()
for(auto & mesh : mMeshes) { {
for (auto & mesh : mMeshes) {
delete mesh; delete mesh;
} }
for(auto & model : mModels) { for (auto & model : mModels) {
delete model; delete model;
} }
delete mSkybox; delete mSkybox;
@ -37,22 +39,25 @@ Scene::~Scene() {
* Public Methods * Public Methods
******************************************************************************/ ******************************************************************************/
template <> MeshRenderer * Scene::addObject(MeshRenderer * object) { template <> MeshRenderer * Scene::addObject(MeshRenderer * object)
{
initSceneObjectName(object); initSceneObjectName(object);
mMeshes.push_back(object); mMeshes.push_back(object);
sceneUpdated(mSceneName); sceneUpdated(mSceneName);
return object; return object;
} }
template <> Model * Scene::addObject(Model * object) { template <> Model * Scene::addObject(Model * object)
{
initSceneObjectName(object); initSceneObjectName(object);
mModels.push_back(object); mModels.push_back(object);
sceneUpdated(mSceneName); sceneUpdated(mSceneName);
return object; return object;
} }
void Scene::draw() { void Scene::draw()
if(!mInit) { {
if (!mInit) {
initializeOpenGLFunctions(); initializeOpenGLFunctions();
init(); init();
mInit = true; mInit = true;
@ -60,62 +65,66 @@ void Scene::draw() {
// Check if there were new models added that still need to be loaded. // Check if there were new models added that still need to be loaded.
// This is for objects added at runtime via click-and-drag events, etc. // This is for objects added at runtime via click-and-drag events, etc.
while(!mModelLoadQueue.empty()) { while (!mModelLoadQueue.empty()) {
auto modelSpec = mModelLoadQueue.front(); auto modelSpec = mModelLoadQueue.front();
// Load the model and add it to the scene. // Load the model and add it to the scene.
addObject(new Model(modelSpec.first.c_str(), modelSpec.second.c_str())); addObject(new Model(modelSpec.first.c_str(), modelSpec.second.c_str()));
mModelLoadQueue.pop(); mModelLoadQueue.pop();
} }
if(mPause) { if (mPause) {
return; return;
} }
if(mSkybox != Q_NULLPTR) { if (mSkybox != Q_NULLPTR) {
mSkybox->draw(); mSkybox->draw();
} }
for(const auto & model : mModels) { for (const auto & model : mModels) {
model->draw(); model->draw();
} }
for(const auto & mesh : mMeshes) { for (const auto & mesh : mMeshes) {
mesh->draw(); mesh->draw();
} }
} }
std::vector<Object *> Scene::getObjects() const { std::vector<Object *> Scene::getObjects() const
{
// All scene objects must inherit from Qtk::Object. // All scene objects must inherit from Qtk::Object.
std::vector<Object *> objects(mMeshes.begin(), mMeshes.end()); std::vector<Object *> objects(mMeshes.begin(), mMeshes.end());
for(const auto & model : mModels) { for (const auto & model : mModels) {
objects.push_back(model); objects.push_back(model);
if(objects.back() == nullptr) { if (objects.back() == nullptr) {
return {}; return {};
} }
} }
return objects; return objects;
} }
Object * Scene::getObject(const QString & name) const { Object * Scene::getObject(const QString & name) const
for(const auto & object : getObjects()) { {
if(object->getName() == name.toStdString()) { for (const auto & object : getObjects()) {
if (object->getName() == name.toStdString()) {
return object; return object;
} }
} }
return Q_NULLPTR; return Q_NULLPTR;
} }
void Scene::setSkybox(Skybox * skybox) { void Scene::setSkybox(Skybox * skybox)
{
delete mSkybox; delete mSkybox;
mSkybox = skybox; mSkybox = skybox;
} }
void Scene::initSceneObjectName(Object * object) { void Scene::initSceneObjectName(Object * object)
if(!mObjectCount.count(object->getName())) { {
if (!mObjectCount.count(object->getName())) {
mObjectCount[object->getName()] = 1; mObjectCount[object->getName()] = 1;
} else { } else {
mObjectCount[object->getName()]++; mObjectCount[object->getName()]++;
} }
auto count = mObjectCount[object->getName()]; auto count = mObjectCount[object->getName()];
if(count > 1) { if (count > 1) {
object->setName(object->getName() + " (" + std::to_string(count) + ")"); object->setName(object->getName() + " (" + std::to_string(count) + ")");
} }
} }

View File

@ -21,7 +21,8 @@
#include "model.h" #include "model.h"
#include "skybox.h" #include "skybox.h"
namespace Qtk { namespace Qtk
{
/** /**
* An abstract Scene class to inherit from when building new scenes. * An abstract Scene class to inherit from when building new scenes.
* *
@ -43,7 +44,8 @@ namespace Qtk {
* If the child scene adds any objects which are not managed (drawn) by this * 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. * base class, the child scene class must also override the `draw()` method.
*/ */
class Scene : public QObject, protected QOpenGLFunctions { class Scene : public QObject, protected QOpenGLFunctions
{
Q_OBJECT Q_OBJECT
public: public:
@ -79,15 +81,17 @@ namespace Qtk {
* It's very possible a client will not want to move objects in the scene * It's very possible a client will not want to move objects in the scene
* using this method. This is intentially not pure virtual. * using this method. This is intentially not pure virtual.
*/ */
virtual void update() { } virtual void update() {}
void loadModel(const QUrl & url) { void loadModel(const QUrl & url)
{
auto fileName = url.fileName().replace(".obj", "").toStdString(); auto fileName = url.fileName().replace(".obj", "").toStdString();
auto filePath = url.toLocalFile().toStdString(); auto filePath = url.toLocalFile().toStdString();
loadModel(fileName, filePath); loadModel(fileName, filePath);
} }
void loadModel(const std::string & name, const std::string & path) { void loadModel(const std::string & name, const std::string & path)
{
// Add the dropped model to the load queue. // Add the dropped model to the load queue.
// This is consumed during rendering of the scene if not empty. // This is consumed during rendering of the scene if not empty.
mModelLoadQueue.emplace(name, path); mModelLoadQueue.emplace(name, path);
@ -114,7 +118,8 @@ namespace Qtk {
/** /**
* @return The number of objects within the scene with the given name. * @return The number of objects within the scene with the given name.
*/ */
[[nodiscard]] uint64_t getObjectCount(const QString & name) { [[nodiscard]] uint64_t getObjectCount(const QString & name)
{
return mObjectCount.count(name.toStdString()) return mObjectCount.count(name.toStdString())
? mObjectCount[name.toStdString()] ? mObjectCount[name.toStdString()]
: 0; : 0;
@ -128,14 +133,16 @@ namespace Qtk {
/** /**
* @return View matrix for the camera attached to this scene. * @return View matrix for the camera attached to this scene.
*/ */
[[nodiscard]] inline static QMatrix4x4 getViewMatrix() { [[nodiscard]] inline static QMatrix4x4 getViewMatrix()
{
return mCamera.toMatrix(); return mCamera.toMatrix();
} }
/** /**
* @return Projection matrix for the current view into the scene. * @return Projection matrix for the current view into the scene.
*/ */
[[nodiscard]] inline static QMatrix4x4 & getProjectionMatrix() { [[nodiscard]] inline static QMatrix4x4 & getProjectionMatrix()
{
return mProjection; return mProjection;
} }
@ -153,15 +160,16 @@ namespace Qtk {
/** /**
* @return All MeshRenderers within the scene. * @return All MeshRenderers within the scene.
*/ */
[[nodiscard]] inline const std::vector<MeshRenderer *> & getMeshes() [[nodiscard]] inline const std::vector<MeshRenderer *> & getMeshes() const
const { {
return mMeshes; return mMeshes;
} }
/** /**
* @return All Models within the scene. * @return All Models within the scene.
*/ */
[[nodiscard]] inline const std::vector<Model *> & getModels() const { [[nodiscard]] inline const std::vector<Model *> & getModels() const
{
return mModels; return mModels;
} }

View File

@ -10,9 +10,10 @@
using namespace Qtk; 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. // The order of the following assignment values helps to visualize.
// clang-format off // clang-format off
@ -203,10 +204,11 @@ Cube::Cube(DrawMode mode) {
} }
} }
Triangle::Triangle(DrawMode mode) { 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 // clang-format off
case QTK_DRAW_ARRAYS: case QTK_DRAW_ARRAYS:

View File

@ -73,7 +73,8 @@
#define UV_RIGHT QVector2D(0.0f, 1.0f) #define UV_RIGHT QVector2D(0.0f, 1.0f)
#define UV_CORNER QVector2D(1.0f, 1.0f) #define UV_CORNER QVector2D(1.0f, 1.0f)
namespace Qtk { namespace Qtk
{
class MeshRenderer; class MeshRenderer;
class Object; class Object;
@ -114,13 +115,14 @@ namespace Qtk {
* @param t Texture coordinates for this shape. * @param t Texture coordinates for this shape.
* @param n Normals for this shape. * @param n Normals for this shape.
*/ */
explicit ShapeBase( explicit ShapeBase(DrawMode mode = QTK_DRAW_ARRAYS, Vertices v = {},
DrawMode mode = QTK_DRAW_ARRAYS, Vertices v = {}, Indices i = {}, Indices i = {}, Colors c = {}, TexCoords t = {},
Colors c = {}, TexCoords t = {}, Normals n = {}) : Normals n = {}) :
mDrawMode(mode), mDrawMode(mode), mVertices(std::move(v)), mColors(std::move(c)),
mVertices(std::move(v)), mColors(std::move(c)),
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 * Accessors
@ -129,14 +131,16 @@ namespace Qtk {
/** /**
* @return Vertex data for this shape. * @return Vertex data for this shape.
*/ */
[[nodiscard]] inline const Vertices & getVertices() const { [[nodiscard]] inline const Vertices & getVertices() const
{
return mVertices; return mVertices;
} }
/** /**
* @return Index data for this shape. * @return Index data for this shape.
*/ */
[[nodiscard]] inline const Indices & getIndexData() const { [[nodiscard]] inline const Indices & getIndexData() const
{
return mIndices; return mIndices;
} }
@ -148,21 +152,24 @@ namespace Qtk {
/** /**
* @return Texture coordinates for this shape. * @return Texture coordinates for this shape.
*/ */
[[nodiscard]] inline const TexCoords & getTexCoords() const { [[nodiscard]] inline const TexCoords & getTexCoords() const
{
return mTexCoords; return mTexCoords;
} }
/** /**
* @return Normals for this shape. * @return Normals for this shape.
*/ */
[[nodiscard]] inline const Normals & getNormals() const { [[nodiscard]] inline const Normals & getNormals() const
{
return mNormals; return mNormals;
} }
/** /**
* @return Stride for texture coordinates on this shape. * @return Stride for texture coordinates on this shape.
*/ */
[[nodiscard]] inline size_t getTexCoordsStride() const { [[nodiscard]] inline size_t getTexCoordsStride() const
{
return mTexCoords.size() * sizeof(mTexCoords[0]); return mTexCoords.size() * sizeof(mTexCoords[0]);
} }
@ -204,14 +211,16 @@ namespace Qtk {
/** /**
* @param value Vertex data to use for this shape. * @param value Vertex data to use for this shape.
*/ */
virtual inline void setVertices(const Vertices & value) { virtual inline void setVertices(const Vertices & value)
{
mVertices = value; mVertices = value;
} }
/** /**
* @param value Index data to use for this shape. * @param value Index data to use for this shape.
*/ */
virtual inline void setIndices(const Indices & value) { virtual inline void setIndices(const Indices & value)
{
mIndices = value; mIndices = value;
} }
@ -223,14 +232,16 @@ namespace Qtk {
/** /**
* @param value Texture coordinates to use for this shape. * @param value Texture coordinates to use for this shape.
*/ */
virtual inline void setTexCoords(const TexCoords & value) { virtual inline void setTexCoords(const TexCoords & value)
{
mTexCoords = value; mTexCoords = value;
} }
/** /**
* @param value Normals to use for this shape. * @param value Normals to use for this shape.
*/ */
virtual inline void setNormals(const Normals & value) { virtual inline void setNormals(const Normals & value)
{
mNormals = value; mNormals = value;
} }

View File

@ -17,36 +17,38 @@ using namespace Qtk;
******************************************************************************/ ******************************************************************************/
Skybox::Skybox(const std::string & name) : Skybox::Skybox(const std::string & name) :
Skybox( Skybox(":/textures/skybox/right.png", ":/textures/skybox/top.png",
":/textures/skybox/right.png", ":/textures/skybox/top.png", ":/textures/skybox/front.png", ":/textures/skybox/left.png",
":/textures/skybox/front.png", ":/textures/skybox/left.png", ":/textures/skybox/bottom.png", ":/textures/skybox/back.png", name)
":/textures/skybox/bottom.png", ":/textures/skybox/back.png", name) {} {
}
Skybox::Skybox(QOpenGLTexture * cubeMap, const std::string & name) { Skybox::Skybox(QOpenGLTexture * cubeMap, const std::string & name)
{
mTexture.setTexture(cubeMap); mTexture.setTexture(cubeMap);
init(); init();
} }
Skybox::Skybox( 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, const std::string & bottom, const std::string & back,
const std::string & bottom, const std::string & back, const std::string & name) :
const std::string & name) :
mVBO(QOpenGLBuffer::VertexBuffer), mVBO(QOpenGLBuffer::VertexBuffer),
mVertices(Cube(QTK_DRAW_ELEMENTS).getVertices()), mVertices(Cube(QTK_DRAW_ELEMENTS).getVertices()),
mIndices(Cube(QTK_DRAW_ELEMENTS).getIndexData()) { mIndices(Cube(QTK_DRAW_ELEMENTS).getIndexData())
{
init(); init();
mTexture.setCubeMap( mTexture.setCubeMap(QImage(right.c_str()).mirrored(), QImage(top.c_str()),
QImage(right.c_str()).mirrored(), QImage(top.c_str()), QImage(front.c_str()), QImage(left.c_str()),
QImage(front.c_str()), QImage(left.c_str()), QImage(bottom.c_str()), QImage(bottom.c_str()), QImage(back.c_str()));
QImage(back.c_str()));
} }
/******************************************************************************* /*******************************************************************************
* Public Member Functions * Public Member Functions
******************************************************************************/ ******************************************************************************/
void Skybox::draw() { void Skybox::draw()
{
glDepthFunc(GL_LEQUAL); glDepthFunc(GL_LEQUAL);
glDepthMask(GL_FALSE); glDepthMask(GL_FALSE);
@ -57,8 +59,8 @@ void Skybox::draw() {
mProgram.setUniformValue("uProjectionMatrix", Scene::getProjectionMatrix()); mProgram.setUniformValue("uProjectionMatrix", Scene::getProjectionMatrix());
mProgram.setUniformValue("uViewMatrix", Scene::getCamera().toMatrix()); mProgram.setUniformValue("uViewMatrix", Scene::getCamera().toMatrix());
mProgram.setUniformValue("uTexture", 0); mProgram.setUniformValue("uTexture", 0);
glDrawElements( glDrawElements(GL_TRIANGLES, mIndices.size(), GL_UNSIGNED_INT,
GL_TRIANGLES, mIndices.size(), GL_UNSIGNED_INT, mIndices.data()); mIndices.data());
mTexture.getOpenGLTexture().bind(); mTexture.getOpenGLTexture().bind();
mProgram.release(); mProgram.release();
@ -73,15 +75,16 @@ void Skybox::draw() {
* Private Member Functions * Private Member Functions
******************************************************************************/ ******************************************************************************/
void Skybox::init() { void Skybox::init()
{
initializeOpenGLFunctions(); initializeOpenGLFunctions();
// Set up shader program // Set up shader program
mProgram.create(); mProgram.create();
mProgram.addShaderFromSourceFile( mProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,
QOpenGLShader::Vertex, ":/shaders/skybox.vert"); ":/shaders/skybox.vert");
mProgram.addShaderFromSourceFile( mProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,
QOpenGLShader::Fragment, ":/shaders/skybox.frag"); ":/shaders/skybox.frag");
mProgram.link(); mProgram.link();
mProgram.bind(); mProgram.bind();

View File

@ -20,13 +20,15 @@
#include "shape.h" #include "shape.h"
#include "texture.h" #include "texture.h"
namespace Qtk { namespace Qtk
{
/** /**
* Skybox object for rendering a skybox within a Scene. * Skybox object for rendering a skybox within a Scene.
* A skybox is typically implemented using a cube map texture centered around * A skybox is typically implemented using a cube map texture centered around
* the camera and projected outwards in all directions. * the camera and projected outwards in all directions.
*/ */
class QTKAPI Skybox : protected QOpenGLFunctions { class QTKAPI Skybox : protected QOpenGLFunctions
{
public: public:
/************************************************************************* /*************************************************************************
* Constructors / Destructors * Constructors / Destructors
@ -48,8 +50,8 @@ namespace Qtk {
* @param cubeMap QOpenGLTexture to use for the new Skybox. * @param cubeMap QOpenGLTexture to use for the new Skybox.
* @param name The objectName to use for the Skybox. * @param name The objectName to use for the Skybox.
*/ */
explicit Skybox( explicit Skybox(QOpenGLTexture * cubeMap,
QOpenGLTexture * cubeMap, const std::string & name = "Skybox"); const std::string & name = "Skybox");
/** /**
* Construct a Skybox. * Construct a Skybox.
@ -62,11 +64,10 @@ namespace Qtk {
* @param back Image to use for the back side of the Skybox. * @param back Image to use for the back side of the Skybox.
* @param name The objectName to use for this Skybox. * @param name The objectName to use for this Skybox.
*/ */
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, const std::string & bottom, const std::string & back,
const std::string & bottom, const std::string & back, const std::string & name = "Skybox");
const std::string & name = "Skybox");
~Skybox() = default; ~Skybox() = default;

View File

@ -14,46 +14,49 @@
using namespace Qtk; using namespace Qtk;
QImage OpenGLTextureFactory::initImage( QImage OpenGLTextureFactory::initImage(const char * image, bool flipX,
const char * image, bool flipX, bool flipY) { bool flipY)
{
// Qt6 limits loaded images to 256MB by default // Qt6 limits loaded images to 256MB by default
QImageReader::setAllocationLimit(1024); QImageReader::setAllocationLimit(1024);
auto loadedImage = QImage(image).mirrored(flipX, flipY); auto loadedImage = QImage(image).mirrored(flipX, flipY);
if(loadedImage.isNull()) { if (loadedImage.isNull()) {
return defaultTexture(); return defaultTexture();
} }
return loadedImage; return loadedImage;
} }
QOpenGLTexture * OpenGLTextureFactory::initTexture( QOpenGLTexture * OpenGLTextureFactory::initTexture(const char * texture,
const char * texture, bool flipX, bool flipY) { bool flipX, bool flipY)
{
QImage image = initImage(texture, flipX, flipY); QImage image = initImage(texture, flipX, flipY);
auto newTexture = new QOpenGLTexture(QOpenGLTexture::Target2D); auto newTexture = new QOpenGLTexture(QOpenGLTexture::Target2D);
newTexture->setData(image); newTexture->setData(image);
newTexture->setWrapMode(QOpenGLTexture::Repeat); newTexture->setWrapMode(QOpenGLTexture::Repeat);
newTexture->setMinMagFilters( newTexture->setMinMagFilters(QOpenGLTexture::LinearMipMapLinear,
QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear); QOpenGLTexture::Linear);
return newTexture; return newTexture;
} }
QOpenGLTexture * OpenGLTextureFactory::initCubeMap(const char * tile) { QOpenGLTexture * OpenGLTextureFactory::initCubeMap(const char * tile)
return initCubeMap( {
QImage(tile), QImage(tile), QImage(tile), QImage(tile), QImage(tile), return initCubeMap(QImage(tile), QImage(tile), QImage(tile), QImage(tile),
QImage(tile)); QImage(tile), QImage(tile));
} }
QOpenGLTexture * OpenGLTextureFactory::initCubeMap( QOpenGLTexture * OpenGLTextureFactory::initCubeMap(
const char * right, const char * top, const char * front, const char * left, const char * right, const char * top, const char * front, const char * left,
const char * bottom, const char * back) { const char * bottom, const char * back)
return initCubeMap( {
QImage(right), QImage(top), QImage(front), QImage(left), QImage(bottom), return initCubeMap(QImage(right), QImage(top), QImage(front), QImage(left),
QImage(back)); QImage(bottom), QImage(back));
} }
QOpenGLTexture * OpenGLTextureFactory::initCubeMap( QOpenGLTexture * OpenGLTextureFactory::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)
{
auto texture = new QOpenGLTexture(QOpenGLTexture::TargetCubeMap); auto texture = new QOpenGLTexture(QOpenGLTexture::TargetCubeMap);
std::vector<QImage> faceTextures = {right, top, front, left, bottom, back}; std::vector<QImage> faceTextures = {right, top, front, left, bottom, back};
// Initialize skybox cubemap texture // Initialize skybox cubemap texture
@ -65,26 +68,25 @@ QOpenGLTexture * OpenGLTextureFactory::initCubeMap(
QOpenGLTexture::CubeMapPositiveZ, QOpenGLTexture::CubeMapNegativeX, QOpenGLTexture::CubeMapPositiveZ, QOpenGLTexture::CubeMapNegativeX,
QOpenGLTexture::CubeMapNegativeY, QOpenGLTexture::CubeMapNegativeZ}; QOpenGLTexture::CubeMapNegativeY, QOpenGLTexture::CubeMapNegativeZ};
int i = 0; int i = 0;
for(const auto & face : faces) { for (const auto & face : faces) {
QImage faceImage(faceTextures[i]); QImage faceImage(faceTextures[i]);
if(faceImage.isNull()) { if (faceImage.isNull()) {
qDebug() << "Error loading cube map image\n"; qDebug() << "Error loading cube map image\n";
faceImage = defaultTexture(); faceImage = defaultTexture();
} }
faceImage = faceImage.convertToFormat(QImage::Format_RGBA8888); faceImage = faceImage.convertToFormat(QImage::Format_RGBA8888);
// On the first iteration, set format and allocate texture storage // On the first iteration, set format and allocate texture storage
if(face == QOpenGLTexture::CubeMapPositiveX) { if (face == QOpenGLTexture::CubeMapPositiveX) {
// This also needs to happen on the first iteration, anyways // This also needs to happen on the first iteration, anyways
texture->setSize( texture->setSize(faceImage.width(), faceImage.height(),
faceImage.width(), faceImage.height(), faceImage.depth()); faceImage.depth());
texture->setFormat(QOpenGLTexture::RGBA8_UNorm); texture->setFormat(QOpenGLTexture::RGBA8_UNorm);
texture->allocateStorage(); texture->allocateStorage();
} }
texture->setData( texture->setData(0, 0, face, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8,
0, 0, face, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, faceImage.constBits());
faceImage.constBits());
i++; i++;
} }

View File

@ -16,30 +16,33 @@
#include "qtkapi.h" #include "qtkapi.h"
namespace Qtk { namespace Qtk
{
/** /**
* Binds shader programs until the end of scope. * Binds shader programs until the end of scope.
* Does nothing if the shader program was already bound. * Does nothing if the shader program was already bound.
* *
* See MeshRenderer::setUniform() for example. * See MeshRenderer::setUniform() for example.
*/ */
class QTKAPI ShaderBindScope { class QTKAPI ShaderBindScope
{
public: public:
/************************************************************************* /*************************************************************************
* Constructors / Destructors * Constructors / Destructors
************************************************************************/ ************************************************************************/
explicit ShaderBindScope( explicit ShaderBindScope(QOpenGLShaderProgram * program,
QOpenGLShaderProgram * program, bool was_locked) : bool was_locked) : mWasBound(was_locked)
mWasBound(was_locked) { {
mProgram = program; mProgram = program;
if(!mWasBound) { if (!mWasBound) {
mProgram->bind(); mProgram->bind();
} }
} }
~ShaderBindScope() { ~ShaderBindScope()
if(!mWasBound) { {
if (!mWasBound) {
mProgram->release(); mProgram->release();
} }
} }
@ -56,7 +59,8 @@ namespace Qtk {
/** /**
* Factories for initializing various OpenGL textures * Factories for initializing various OpenGL textures
*/ */
class QTKAPI OpenGLTextureFactory { class QTKAPI OpenGLTextureFactory
{
public: public:
/************************************************************************* /*************************************************************************
* Constructors / Destructors * Constructors / Destructors
@ -76,8 +80,8 @@ namespace Qtk {
* @param flipY If true the image will be flipped on Y axis. * @param flipY If true the image will be flipped on Y axis.
* @return QImage object. * @return QImage object.
*/ */
static QImage initImage( static QImage initImage(const char * image, bool flipX = false,
const char * image, bool flipX = false, bool flipY = false); bool flipY = false);
/** /**
* QOpenGLTexture factory * QOpenGLTexture factory
@ -88,8 +92,9 @@ namespace Qtk {
* @param flipY If true the image will be flipped on Y axis. * @param flipY If true the image will be flipped on Y axis.
* @return Pointer to an initialized QOpenGLTexture object. * @return Pointer to an initialized QOpenGLTexture object.
*/ */
static QOpenGLTexture * initTexture( static QOpenGLTexture * initTexture(const char * texture,
const char * texture, bool flipX = false, bool flipY = false); bool flipX = false,
bool flipY = false);
/** /**
* Cube map factory for initializing all sides of a CubeMap. * Cube map factory for initializing all sides of a CubeMap.
@ -128,12 +133,14 @@ namespace Qtk {
* @param back Path to image for the back side of the CubeMap. * @param back Path to image for the back side of the CubeMap.
* @return Pointer to an initialized QOpenGLTexture object. * @return Pointer to an initialized QOpenGLTexture object.
*/ */
static QOpenGLTexture * initCubeMap( static QOpenGLTexture * initCubeMap(const char * right, const char * top,
const char * right, const char * top, const char * front, const char * front, const char * left,
const char * left, const char * bottom, const char * back); const char * bottom,
const char * back);
/// The texture used in place of a missing texture. /// The texture used in place of a missing texture.
static QImage defaultTexture() { static QImage defaultTexture()
{
// Use plaster for default texture if image fails to load. // Use plaster for default texture if image fails to load.
// This prevents segfaults when loading a texture that doesn't exist. // This prevents segfaults when loading a texture that doesn't exist.
// TODO: Replace with a '?' texture to indicate missing texture. // TODO: Replace with a '?' texture to indicate missing texture.
@ -151,7 +158,8 @@ namespace Qtk {
* TODO: Struct for (re)storing texture state * TODO: Struct for (re)storing texture state
* A struct to store flipX, flipY and other initial state needed to copy * A struct to store flipX, flipY and other initial state needed to copy
*/ */
class Texture { class Texture
{
public: public:
/************************************************************************* /*************************************************************************
* Typedefs * Typedefs
@ -169,7 +177,8 @@ namespace Qtk {
* *
* @param value Texture to copy. * @param value Texture to copy.
*/ */
Texture(const Texture & value) { Texture(const Texture & value)
{
mOpenGLTexture = OpenGLTextureFactory::initTexture(value.mPath); mOpenGLTexture = OpenGLTextureFactory::initTexture(value.mPath);
mPath = value.mPath; mPath = value.mPath;
} }
@ -179,10 +188,12 @@ namespace Qtk {
* @param flipX True if texture is to be flipped on the X axis. * @param flipX True if texture is to be flipped on the X axis.
* @param flipY True if texture is to be flipped on the Y axis. * @param flipY True if texture is to be flipped on the Y axis.
*/ */
explicit Texture( explicit Texture(const char * path, bool flipX = false,
const char * path, bool flipX = false, bool flipY = false) : bool flipY = false) :
mOpenGLTexture(OpenGLTextureFactory::initTexture(path, flipX, flipY)), mOpenGLTexture(OpenGLTextureFactory::initTexture(path, flipX, flipY)),
mPath(path) {} mPath(path)
{
}
/** /**
* Construct a Texture using an existing QOpenGLTexture. * Construct a Texture using an existing QOpenGLTexture.
@ -200,7 +211,8 @@ namespace Qtk {
/** /**
* @return True if the OpenGL texture has been initialized. * @return True if the OpenGL texture has been initialized.
*/ */
[[nodiscard]] inline bool hasTexture() const { [[nodiscard]] inline bool hasTexture() const
{
return mOpenGLTexture != Q_NULLPTR; return mOpenGLTexture != Q_NULLPTR;
} }
@ -211,7 +223,8 @@ namespace Qtk {
/** /**
* @return QOpenGLTexture associated with this Texture. * @return QOpenGLTexture associated with this Texture.
*/ */
[[nodiscard]] inline QOpenGLTexture & getOpenGLTexture() const { [[nodiscard]] inline QOpenGLTexture & getOpenGLTexture() const
{
return *mOpenGLTexture; return *mOpenGLTexture;
} }
@ -231,8 +244,9 @@ namespace Qtk {
* @param flipX True if texture is to be flipped on the X axis. * @param flipX True if texture is to be flipped on the X axis.
* @param flipY True if texture is to be flipped on the Y axis. * @param flipY True if texture is to be flipped on the Y axis.
*/ */
inline void setTexture( inline void setTexture(const std::string & path, bool flipX = false,
const std::string & path, bool flipX = false, bool flipY = false) { bool flipY = false)
{
setTexture(path.c_str(), flipX, flipY); setTexture(path.c_str(), flipX, flipY);
} }
@ -241,8 +255,9 @@ namespace Qtk {
* @param flipX True if texture is to be flipped on the X axis. * @param flipX True if texture is to be flipped on the X axis.
* @param flipY True if texture is to be flipped on the Y axis. * @param flipY True if texture is to be flipped on the Y axis.
*/ */
inline void setTexture( inline void setTexture(const char * path, bool flipX = false,
const char * path, bool flipX = false, bool flipY = false) { bool flipY = false)
{
mOpenGLTexture = OpenGLTextureFactory::initTexture(path, flipX, flipY); mOpenGLTexture = OpenGLTextureFactory::initTexture(path, flipX, flipY);
mPath = path; mPath = path;
} }
@ -252,7 +267,8 @@ namespace Qtk {
* *
* @param path Path to texture to use for all sides of the cube map. * @param path Path to texture to use for all sides of the cube map.
*/ */
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;
} }
@ -267,11 +283,12 @@ namespace Qtk {
* @param bottom Path to texture to use for bottom cube map side. * @param bottom Path to texture to use for bottom cube map side.
* @param back Path to texture to use for back cube map side. * @param back Path to texture to use for back cube map side.
*/ */
virtual inline void setCubeMap( virtual inline void setCubeMap(const char * right, const char * top,
const char * right, const char * top, const char * front, const char * front, const char * left,
const char * left, const char * bottom, const char * back) { const char * bottom, const char * back)
mOpenGLTexture = OpenGLTextureFactory::initCubeMap( {
right, top, front, left, bottom, back); mOpenGLTexture = OpenGLTextureFactory::initCubeMap(right, top, front,
left, bottom, back);
} }
/** /**
@ -284,11 +301,12 @@ namespace Qtk {
* @param bottom Path to texture to use for bottom cube map side. * @param bottom Path to texture to use for bottom cube map side.
* @param back Path to texture to use for back cube map side. * @param back Path to texture to use for back cube map side.
*/ */
virtual inline void setCubeMap( virtual inline void setCubeMap(const QImage & right, const QImage & top,
const QImage & right, const QImage & top, const QImage & front, const QImage & front, const QImage & left,
const QImage & left, const QImage & bottom, const QImage & back) { const QImage & bottom, const QImage & back)
mOpenGLTexture = OpenGLTextureFactory::initCubeMap( {
right, top, front, left, bottom, back); mOpenGLTexture = OpenGLTextureFactory::initCubeMap(right, top, front,
left, bottom, back);
} }
private: private:
@ -299,7 +317,8 @@ namespace Qtk {
/** /**
* @param texture QOpenGLTexture to use for this Texture. * @param texture QOpenGLTexture to use for this Texture.
*/ */
inline void setTexture(QOpenGLTexture * texture) { inline void setTexture(QOpenGLTexture * texture)
{
mOpenGLTexture = texture; mOpenGLTexture = texture;
} }

View File

@ -19,44 +19,52 @@ const QVector3D Transform3D::LocalRight(1.0f, 0.0f, 0.0f);
* Public Methods * Public Methods
******************************************************************************/ ******************************************************************************/
void Transform3D::translate(const QVector3D & dt) { void Transform3D::translate(const QVector3D & dt)
{
m_dirty = true; m_dirty = true;
mTranslation += dt; mTranslation += dt;
} }
void Transform3D::scale(const QVector3D & ds) { void Transform3D::scale(const QVector3D & ds)
{
m_dirty = true; m_dirty = true;
mScale *= ds; mScale *= ds;
} }
void Transform3D::grow(const QVector3D & ds) { void Transform3D::grow(const QVector3D & ds)
{
m_dirty = true; m_dirty = true;
mScale += ds; mScale += ds;
} }
void Transform3D::rotate(const QQuaternion & dr) { void Transform3D::rotate(const QQuaternion & dr)
{
m_dirty = true; m_dirty = true;
mRotation = dr * mRotation; mRotation = dr * mRotation;
} }
void Transform3D::setTranslation(const QVector3D & t) { void Transform3D::setTranslation(const QVector3D & t)
{
m_dirty = true; m_dirty = true;
mTranslation = t; mTranslation = t;
} }
void Transform3D::setScale(const QVector3D & s) { void Transform3D::setScale(const QVector3D & s)
{
m_dirty = true; m_dirty = true;
mScale = s; mScale = s;
} }
void Transform3D::setRotation(const QQuaternion & r) { void Transform3D::setRotation(const QQuaternion & r)
{
m_dirty = true; m_dirty = true;
mRotation = r; mRotation = r;
} }
const QMatrix4x4 & Transform3D::toMatrix() { const QMatrix4x4 & Transform3D::toMatrix()
if(m_dirty) { {
if (m_dirty) {
m_dirty = false; m_dirty = false;
mWorld.setToIdentity(); mWorld.setToIdentity();
mWorld.translate(mTranslation); mWorld.translate(mTranslation);
@ -66,15 +74,18 @@ const QMatrix4x4 & Transform3D::toMatrix() {
return mWorld; return mWorld;
} }
QVector3D Transform3D::getForward() const { QVector3D Transform3D::getForward() const
{
return mRotation.rotatedVector(LocalForward); return mRotation.rotatedVector(LocalForward);
} }
QVector3D Transform3D::getUp() const { QVector3D Transform3D::getUp() const
{
return mRotation.rotatedVector(LocalUp); return mRotation.rotatedVector(LocalUp);
} }
QVector3D Transform3D::getRight() const { QVector3D Transform3D::getRight() const
{
return mRotation.rotatedVector(LocalRight); return mRotation.rotatedVector(LocalRight);
} }
@ -82,10 +93,12 @@ QVector3D Transform3D::getRight() const {
* Private Methods * Private Methods
******************************************************************************/ ******************************************************************************/
namespace Qtk { namespace Qtk
{
#ifndef QT_NO_DEBUG_STREAM #ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const Transform3D & transform) { QDebug operator<<(QDebug dbg, const Transform3D & transform)
{
dbg << "Transform3D\n{\n"; dbg << "Transform3D\n{\n";
dbg << "Position: <" << transform.getTranslation().x() << ", " dbg << "Position: <" << transform.getTranslation().x() << ", "
<< transform.getTranslation().y() << ", " << transform.getTranslation().y() << ", "
@ -102,14 +115,16 @@ namespace Qtk {
#endif #endif
#ifndef QT_NO_DATASTREAM #ifndef QT_NO_DATASTREAM
QDataStream & operator<<(QDataStream & out, const Transform3D & transform) { QDataStream & operator<<(QDataStream & out, const Transform3D & transform)
{
out << transform.mTranslation; out << transform.mTranslation;
out << transform.mScale; out << transform.mScale;
out << transform.mRotation; out << transform.mRotation;
return out; return out;
} }
QDataStream & operator>>(QDataStream & in, Transform3D & transform) { QDataStream & operator>>(QDataStream & in, Transform3D & transform)
{
in >> transform.mTranslation; in >> transform.mTranslation;
in >> transform.mScale; in >> transform.mScale;
in >> transform.mRotation; in >> transform.mRotation;

View File

@ -20,11 +20,13 @@
#include "qtkapi.h" #include "qtkapi.h"
namespace Qtk { namespace Qtk
{
/** /**
* Transform3D class to represent and modify object position in 3D space. * Transform3D class to represent and modify object position in 3D space.
*/ */
class QTKAPI Transform3D { class QTKAPI Transform3D
{
public: public:
/************************************************************************* /*************************************************************************
* Constructors, Destructors * Constructors, Destructors
@ -32,7 +34,9 @@ namespace Qtk {
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)
{
}
/************************************************************************* /*************************************************************************
* Public Methods * Public Methods
@ -48,7 +52,8 @@ namespace Qtk {
* @param dy Y translation from last to current position. * @param dy Y translation from last to current position.
* @param dz Z translation from last to current position. * @param dz Z translation from last to current position.
*/ */
inline void translate(float dx, float dy, float dz) { inline void translate(float dx, float dy, float dz)
{
translate(QVector3D(dx, dy, dz)); translate(QVector3D(dx, dy, dz));
} }
@ -66,7 +71,8 @@ namespace Qtk {
* @param dy Amount to scale on the Y axis. * @param dy Amount to scale on the Y axis.
* @param dz Amount to scale on the Z axis. * @param dz Amount to scale on the Z axis.
*/ */
inline void scale(float dx, float dy, float dz) { inline void scale(float dx, float dy, float dz)
{
scale(QVector3D(dx, dy, dz)); scale(QVector3D(dx, dy, dz));
} }
@ -75,7 +81,8 @@ namespace Qtk {
* *
* @param factor Scalar to apply to all axis of the object. * @param factor Scalar to apply to all axis of the object.
*/ */
inline void scale(float factor) { inline void scale(float factor)
{
scale(QVector3D(factor, factor, factor)); scale(QVector3D(factor, factor, factor));
} }
@ -89,14 +96,16 @@ namespace Qtk {
* @param dy Amount to grow Y axis. * @param dy Amount to grow Y axis.
* @param dz Amount to grow Z axis. * @param dz Amount to grow Z axis.
*/ */
inline void grow(float dx, float dy, float dz) { inline void grow(float dx, float dy, float dz)
{
grow(QVector3D(dx, dy, dz)); grow(QVector3D(dx, dy, dz));
} }
/** /**
* @param factor Amount to grow all axis equally. * @param factor Amount to grow all axis equally.
*/ */
inline void grow(float factor) { inline void grow(float factor)
{
grow(QVector3D(factor, factor, factor)); grow(QVector3D(factor, factor, factor));
} }
@ -109,7 +118,8 @@ namespace Qtk {
* @param angle Angle to rotate. * @param angle Angle to rotate.
* @param axis Axis to rotate apply the rotation on. * @param axis Axis to rotate apply the rotation on.
*/ */
inline void rotate(float angle, const QVector3D & axis) { inline void rotate(float angle, const QVector3D & axis)
{
rotate(QQuaternion::fromAxisAndAngle(axis, angle)); rotate(QQuaternion::fromAxisAndAngle(axis, angle));
} }
@ -121,7 +131,8 @@ namespace Qtk {
* @param ay Y axis to apply the rotation on. * @param ay Y axis to apply the rotation on.
* @param az Z axis to apply the rotation on. * @param az Z axis to apply the rotation on.
*/ */
inline void rotate(float angle, float ax, float ay, float az) { inline void rotate(float angle, float ax, float ay, float az)
{
rotate(QQuaternion::fromAxisAndAngle(ax, ay, az, angle)); rotate(QQuaternion::fromAxisAndAngle(ax, ay, az, angle));
} }
@ -139,7 +150,8 @@ namespace Qtk {
* @param y Y position to set transform. * @param y Y position to set transform.
* @param z Z position to set transform. * @param z Z position to set transform.
*/ */
inline void setTranslation(float x, float y, float z) { inline void setTranslation(float x, float y, float z)
{
setTranslation(QVector3D(x, y, z)); setTranslation(QVector3D(x, y, z));
} }
@ -153,7 +165,8 @@ namespace Qtk {
* @param y Y axis scale to set for this transform. * @param y Y axis scale to set for this transform.
* @param z Z axis scale to set for this transform. * @param z Z axis scale to set for this transform.
*/ */
inline void setScale(float x, float y, float z) { inline void setScale(float x, float y, float z)
{
setScale(QVector3D(x, y, z)); setScale(QVector3D(x, y, z));
} }
@ -171,7 +184,8 @@ namespace Qtk {
* @param angle Angle to set for rotation. * @param angle Angle to set for rotation.
* @param axis Axis to set rotation for. * @param axis Axis to set rotation for.
*/ */
inline void setRotation(float angle, const QVector3D & axis) { inline void setRotation(float angle, const QVector3D & axis)
{
setRotation(QQuaternion::fromAxisAndAngle(axis, angle)); setRotation(QQuaternion::fromAxisAndAngle(axis, angle));
} }
@ -183,7 +197,8 @@ namespace Qtk {
* @param ay Y axis to set angle for. * @param ay Y axis to set angle for.
* @param az Z axis to set angle for. * @param az Z axis to set angle for.
*/ */
inline void setRotation(float angle, float ax, float ay, float az) { inline void setRotation(float angle, float ax, float ay, float az)
{
setRotation(QQuaternion::fromAxisAndAngle(ax, ay, az, angle)); setRotation(QQuaternion::fromAxisAndAngle(ax, ay, az, angle));
} }
@ -194,7 +209,8 @@ namespace Qtk {
/** /**
* @return Translation for this transform. * @return Translation for this transform.
*/ */
[[nodiscard]] inline const QVector3D & getTranslation() const { [[nodiscard]] inline const QVector3D & getTranslation() const
{
return mTranslation; return mTranslation;
} }
@ -206,7 +222,8 @@ namespace Qtk {
/** /**
* @return Rotation for this transform. * @return Rotation for this transform.
*/ */
[[nodiscard]] inline const QQuaternion & getRotation() const { [[nodiscard]] inline const QQuaternion & getRotation() const
{
return mRotation; return mRotation;
} }
@ -250,10 +267,10 @@ namespace Qtk {
bool m_dirty; bool m_dirty;
#ifndef QT_NO_DATASTREAM #ifndef QT_NO_DATASTREAM
friend QDataStream & operator<<( friend QDataStream & operator<<(QDataStream & out,
QDataStream & out, const Transform3D & transform); const Transform3D & transform);
friend QDataStream & operator>>( friend QDataStream & operator>>(QDataStream & in,
QDataStream & in, Transform3D & transform); Transform3D & transform);
#endif #endif
}; };