Compare commits

...

5 Commits

Author SHA1 Message Date
Shaun Reed f78e41dc76 Work on texture class
+ Set up TextureManager class to handle static texture map
2022-08-06 15:21:20 -04:00
Shaun Reed 26200d39a2 Work on Texture class 2022-08-06 15:21:20 -04:00
Shaun Reed 132491b28d Refactor 2022-08-06 15:21:18 -04:00
Shaun Reed 52521dc331 Add MacOS CI
+ (@-OgreTransporter) Merge patches from #4
2022-08-06 15:09:59 -04:00
Shaun Reed 5452520324 Windows updates (@OgreTransporter)
+ Fix resource path on Windows
+ Fix missing OpenGL functions on Windows
+ Create static library
+ Fix CMake for newer assimp versions
+ Closes #2
2022-08-01 23:26:13 -04:00
22 changed files with 301 additions and 229 deletions

View File

@ -6,21 +6,40 @@ on:
workflow_dispatch: workflow_dispatch:
jobs: jobs:
Ubuntu: Build-Qtk:
runs-on: ubuntu-latest strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
include:
- os: ubuntu-latest
CMAKE_PARAMS: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.3.1/gcc_64/
- os: macos-latest
CMAKE_PARAMS: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.3.1/gcc_64/ -DASSIMP_NEW_INTERFACE=on
runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Install Qt - name: Install Qt
uses: jurplel/install-qt-action@v2 uses: jurplel/install-qt-action@v2
with: with:
version: '6.2.3' version: '6.3.1'
- name: Install Assimp - name: Install Assimp Linux
if: matrix.os == 'ubuntu-latest'
shell: bash
run: | run: |
sudo apt install libassimp-dev -y sudo apt install libassimp-dev -y
- name: Install Assimp MacOS
if: matrix.os == 'macos-latest'
shell: bash
run: |
brew install assimp
- name: Build Qtk - name: Build Qtk
shell: bash
run: | run: |
mkdir build && cd build mkdir build && cd build
cmake .. -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.2.3/gcc_64/ && cmake --build . cmake .. ${{ matrix.CMAKE_PARAMS }} && cmake --build .

View File

@ -27,30 +27,25 @@ if (NOT Qt6_FOUND)
message(FATAL_ERROR "Specify path to Qt6 with `cmake -DCMAKE_PREFIX_PATH=/path/to/Qt/6.x.x/gcc_64 -S /path/to/qtk -B /path/to/qtk/build && cmake --build /path/to/qtk/build -j $(nprocs)`") message(FATAL_ERROR "Specify path to Qt6 with `cmake -DCMAKE_PREFIX_PATH=/path/to/Qt/6.x.x/gcc_64 -S /path/to/qtk -B /path/to/qtk/build && cmake --build /path/to/qtk/build -j $(nprocs)`")
endif() endif()
# Add our Qt resources.qrc file to our application
set(SOURCES app/main.cpp)
qt6_add_big_resources(SOURCES resources.qrc)
add_executable(
qtk # Executable name
${SOURCES} # Executable source code
)
################################################################################ ################################################################################
# External Libraries # External Libraries
################################################################################ ################################################################################
# https://github.com/assimp/assimp/commit/6ac8279977c3a54118551e549d77329497116f66 # https://github.com/assimp/assimp/commit/6ac8279977c3a54118551e549d77329497116f66
find_package(assimp REQUIRED) find_package(assimp REQUIRED)
option(ASSIMP_NEW_INTERFACE "Use assimp::assimp as target instead of assimp" OFF)
################################################################################
# Custom Libraries
################################################################################
# Mainwidget
include(GenerateExportHeader) include(GenerateExportHeader)
add_library(main-widget SHARED
################################################################################
# Final Application
################################################################################
# Add our Qt resources.qrc file to our application
set(SOURCES app/main.cpp)
qt6_add_big_resources(SOURCES resources.qrc)
qt_add_executable(qtk ${SOURCES})
set(SOURCES
src/mainwidget.cpp src/mainwidget.h src/mainwidget.cpp src/mainwidget.h
src/mainwindow.cpp src/mainwindow.h src/mainwindow.ui src/mainwindow.cpp src/mainwindow.h src/mainwindow.ui
src/input.cpp src/input.h src/input.cpp src/input.h
@ -65,21 +60,28 @@ add_library(main-widget SHARED
src/scene.cpp src/scene.h src/scene.cpp src/scene.h
src/resourcemanager.cpp src/resourcemanager.h src/resourcemanager.cpp src/resourcemanager.h
) )
qt_add_library(main-widget STATIC ${SOURCES})
target_include_directories(main-widget PUBLIC src/) target_include_directories(main-widget PUBLIC src/)
target_link_libraries(main-widget PRIVATE assimp) if(ASSIMP_NEW_INTERFACE)
target_link_libraries(main-widget PUBLIC Qt${QT_VERSION_MAJOR}::OpenGLWidgets) target_link_libraries(main-widget PRIVATE assimp::assimp)
else()
target_link_libraries(main-widget PRIVATE assimp)
endif()
target_link_libraries(main-widget PUBLIC Qt6::OpenGLWidgets)
if(WIN32)
find_package(OpenGL REQUIRED)
target_link_libraries(main-widget PUBLIC OpenGL::GL)
endif()
################################################################################
# Final Application
################################################################################
# Link qtk executable to main main-widget library
target_link_libraries(qtk PUBLIC main-widget) target_link_libraries(qtk PUBLIC main-widget)
# Link qtk executable to main main-widget library
set_target_properties(qtk PROPERTIES set_target_properties(qtk PROPERTIES
WIN32_EXECUTABLE TRUE WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
) )
generate_export_header(main-widget) generate_export_header(main-widget)

View File

@ -8,8 +8,8 @@
#include <QApplication> #include <QApplication>
#include <QLabel> #include <QLabel>
#include <QSurfaceFormat>
#include <mainwidget.h>
#include <mainwindow.h> #include <mainwindow.h>

View File

@ -23,8 +23,8 @@ const QMatrix4x4 & Camera3D::toMatrix()
{ {
mWorld.setToIdentity(); mWorld.setToIdentity();
// Qt6 renamed QMatrix4x4::conjugate() to conjugated() // Qt6 renamed QMatrix4x4::conjugate() to conjugated()
mWorld.rotate(mTransform.rotation().conjugated()); mWorld.rotate(mTransform.getRotation().conjugated());
mWorld.translate(-mTransform.translation()); mWorld.translate(-mTransform.getTranslation());
return mWorld; return mWorld;
} }

View File

@ -24,18 +24,18 @@ public:
// Accessors // Accessors
inline Transform3D & transform() { return mTransform;} inline Transform3D & transform() { return mTransform;}
inline const QVector3D & translation() const inline const QVector3D & translation() const
{ return mTransform.translation();} { return mTransform.getTranslation();}
inline const QQuaternion & rotation() const inline const QQuaternion & rotation() const
{ return mTransform.rotation();} { return mTransform.getRotation();}
const QMatrix4x4 & toMatrix(); const QMatrix4x4 & toMatrix();
// Queries // Queries
inline QVector3D forward() const inline QVector3D forward() const
{ return mTransform.rotation().rotatedVector(LocalForward);} { return mTransform.getRotation().rotatedVector(LocalForward);}
inline QVector3D right() const inline QVector3D right() const
{ return mTransform.rotation().rotatedVector(LocalRight);} { return mTransform.getRotation().rotatedVector(LocalRight);}
inline QVector3D up() const inline QVector3D up() const
{ return mTransform.rotation().rotatedVector(LocalUp);} { return mTransform.getRotation().rotatedVector(LocalUp);}
private: private:
Transform3D mTransform; Transform3D mTransform;

View File

@ -62,8 +62,8 @@ void MainWidget::initObjects()
// The Object class only stores basic QOpenGL* members and shape data // The Object class only stores basic QOpenGL* members and shape data
// + Within mainwidget, mObject serves as a basic QOpenGL example // + Within mainwidget, mObject serves as a basic QOpenGL example
mObject = new Object("testObject"); mObject = new Object("testObject");
mObject->setVertices(Cube(QTK_DRAW_ELEMENTS).vertices()); mObject->setVertices(Cube(QTK_DRAW_ELEMENTS).getVertices());
mObject->setIndices(Cube(QTK_DRAW_ELEMENTS).indices()); mObject->setIndices(Cube(QTK_DRAW_ELEMENTS).getIndexData());
mObject->mProgram.create(); mObject->mProgram.create();
mObject->mProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, mObject->mProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,
":/solid-ambient.vert"); ":/solid-ambient.vert");
@ -79,13 +79,15 @@ void MainWidget::initObjects()
mObject->mVBO.setUsagePattern(QOpenGLBuffer::StaticDraw); mObject->mVBO.setUsagePattern(QOpenGLBuffer::StaticDraw);
mObject->mVBO.bind(); mObject->mVBO.bind();
mObject->mVBO.allocate(mObject->vertices().data(), mObject->mVBO.allocate(
mObject->vertices().size() mObject->getVertices().data(),
* sizeof(mObject->vertices()[0])); mObject->getVertices().size() * sizeof(mObject->getVertices()[0])
);
mObject->mProgram.enableAttributeArray(0); mObject->mProgram.enableAttributeArray(0);
mObject->mProgram.setAttributeBuffer(0, GL_FLOAT, 0, mObject->mProgram.setAttributeBuffer(
3, sizeof(mObject->vertices()[0])); 0, GL_FLOAT, 0, 3, sizeof(mObject->getVertices()[0])
);
mObject->mProgram.setUniformValue("uColor", QVector3D(1.0f, 0.0f, 0.0f)); mObject->mProgram.setUniformValue("uColor", QVector3D(1.0f, 0.0f, 0.0f));
mObject->mProgram.setUniformValue("uLightColor", WHITE); mObject->mProgram.setUniformValue("uLightColor", WHITE);
mObject->mProgram.setUniformValue("uAmbientStrength", 0.75f); mObject->mProgram.setUniformValue("uAmbientStrength", 0.75f);
@ -116,8 +118,8 @@ void MainWidget::paintGL()
mObject->mProgram.setUniformValue("uModel", mObject->mTransform.toMatrix()); mObject->mProgram.setUniformValue("uModel", mObject->mTransform.toMatrix());
mObject->mProgram.setUniformValue("uView", Scene::Camera().toMatrix()); mObject->mProgram.setUniformValue("uView", Scene::Camera().toMatrix());
mObject->mProgram.setUniformValue("uProjection", Scene::Projection()); mObject->mProgram.setUniformValue("uProjection", Scene::Projection());
glDrawElements(GL_TRIANGLES, mObject->indices().size(), glDrawElements(GL_TRIANGLES, mObject->getIndexData().size(),
GL_UNSIGNED_INT, mObject->indices().data()); GL_UNSIGNED_INT, mObject->getIndexData().data());
mObject->mVAO.release(); mObject->mVAO.release();
mObject->mProgram.release(); mObject->mProgram.release();
} }

View File

@ -22,7 +22,7 @@ class Model;
class Object; class Object;
class Scene; class Scene;
class Skybox; class Skybox;
class Texture; class OpenGLTextureFactory;
class MainWidget : public QOpenGLWidget, class MainWidget : public QOpenGLWidget,
protected QOpenGLFunctions { protected QOpenGLFunctions {

View File

@ -86,11 +86,11 @@ struct ShapeBase {
: mVertices(v), mColors(c), mIndices(i), mTexCoords(t), mNormals(n) : mVertices(v), mColors(c), mIndices(i), mTexCoords(t), mNormals(n)
{} {}
inline const Vertices & vertices() const { return mVertices;} inline const Vertices & getVertices() const { return mVertices;}
inline const Indices & indices() const { return mIndices;} inline const Indices & getIndexData() const { return mIndices;}
inline const Colors & colors() const { return mColors;} inline const Colors & getColors() const { return mColors;}
inline const TexCoords & texCoords() const { return mTexCoords;} inline const TexCoords & getTexCoords() const { return mTexCoords;}
inline const Normals & normals() const { return mNormals;} inline const Normals & getNormals() const { return mNormals;}
protected: protected:
DrawMode mDrawMode; DrawMode mDrawMode;

View File

@ -29,9 +29,6 @@ MeshRenderer::MeshRenderer(const char * name, const ShapeBase & shape)
MeshRenderer::~MeshRenderer() MeshRenderer::~MeshRenderer()
{ {
if (mHasTexture) {
mTexture->destroy();
}
sInstances.remove(mName); sInstances.remove(mName);
} }
@ -68,9 +65,9 @@ void MeshRenderer::init()
// Combine position and color data into one vector, allowing us to use one VBO // Combine position and color data into one vector, allowing us to use one VBO
Vertices combined; Vertices combined;
combined.reserve(vertices().size() + colors().size()); combined.reserve(getVertices().size() + getColors().size());
combined.insert(combined.end(), vertices().begin(), vertices().end()); combined.insert(combined.end(), getVertices().begin(), getVertices().end());
combined.insert(combined.end(), colors().begin(), colors().end()); combined.insert(combined.end(), getColors().begin(), getColors().end());
mVBO.allocate(combined.data(), mVBO.allocate(combined.data(),
combined.size() * sizeof(combined[0])); combined.size() * sizeof(combined[0]));
@ -82,7 +79,7 @@ void MeshRenderer::init()
// 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(1, GL_FLOAT, mProgram.setAttributeBuffer(1, GL_FLOAT,
vertices().size() * sizeof(vertices()[0]), getVertices().size() * sizeof(getVertices()[0]),
3, sizeof(QVector3D)); 3, sizeof(QVector3D));
mVBO.release(); mVBO.release();
@ -96,15 +93,15 @@ void MeshRenderer::draw()
mProgram.bind(); mProgram.bind();
mVAO.bind(); mVAO.bind();
if(mHasTexture) { if(mTexture.hasTexture()) {
mTexture->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, vertices().size()); glDrawArrays(mDrawType, 0, getVertices().size());
} }
else if (mShape.mDrawMode == QTK_DRAW_ELEMENTS else if (mShape.mDrawMode == QTK_DRAW_ELEMENTS
|| mShape.mDrawMode == QTK_DRAW_ELEMENTS_NORMALS) { || mShape.mDrawMode == QTK_DRAW_ELEMENTS_NORMALS) {
@ -112,8 +109,8 @@ void MeshRenderer::draw()
GL_UNSIGNED_INT, mShape.mIndices.data()); GL_UNSIGNED_INT, mShape.mIndices.data());
} }
if(mHasTexture) { if(mTexture.hasTexture()) {
mTexture->release(); mTexture.getOpenGLTexture().release();
} }
mVAO.release(); mVAO.release();
@ -137,29 +134,17 @@ void MeshRenderer::setUniformMVP(const char * model, const char * view,
void MeshRenderer::setColor(const QVector3D & color) void MeshRenderer::setColor(const QVector3D & color)
{ {
if (mShape.mColors.empty()) { if (mShape.mColors.empty()) {
for (const auto & vertex : mShape.vertices()) { for (const auto & vertex : mShape.getVertices()) {
mShape.mColors.push_back(color); mShape.mColors.push_back(color);
} }
} }
else { else {
for (int i = 0; i < mShape.colors().size(); i++) { for (int i = 0; i < mShape.getColors().size(); i++) {
mShape.mColors[i] = color; mShape.mColors[i] = color;
} }
} }
} }
void MeshRenderer::setTexture(const char * path)
{
mTexture = new QOpenGLTexture(*Texture::initImage(path));
mHasTexture = true;
}
void MeshRenderer::setTexture(QOpenGLTexture * texture)
{
mTexture = texture;
mHasTexture = true;
}
/******************************************************************************* /*******************************************************************************
* Inherited Virtual Member Functions * Inherited Virtual Member Functions

View File

@ -11,15 +11,17 @@
#include <mesh.h> #include <mesh.h>
#include <object.h> #include <object.h>
#include <utility>
class MeshRenderer : public Object { class MeshRenderer : public Object {
public: public:
// Delegate constructors // Delegate constructors
MeshRenderer(const char * name, Vertices vertices, Indices indices, MeshRenderer(const char * name, Vertices vertices, Indices indices,
DrawMode mode=QTK_DRAW_ARRAYS) DrawMode mode=QTK_DRAW_ARRAYS)
: MeshRenderer(name, ShapeBase(mode, vertices, indices)) : MeshRenderer(name, ShapeBase(mode, std::move(vertices), std::move(indices)))
{} {}
MeshRenderer(const char * name) explicit MeshRenderer(const char * name)
: MeshRenderer(name, Cube(QTK_DRAW_ELEMENTS)) : MeshRenderer(name, Cube(QTK_DRAW_ELEMENTS))
{} {}
// Constructor // Constructor
@ -54,11 +56,6 @@ public:
void setUniformMVP(const char * model="uModel", const char * view="uView", void setUniformMVP(const char * model="uModel", const char * view="uView",
const char * projection="uProjection"); const char * projection="uProjection");
// Sets the texture to the image at the given path
// + Sets mHasTexture to enable texture binding in draw()
void setTexture(const char * path);
void setTexture(QOpenGLTexture * texture);
// These functions modify data stored in a VBO // These functions modify data stored in a VBO
// + After calling them, the VBO will need to be reallocated // + After calling them, the VBO will need to be reallocated
void setShape(const Shape & value) override; void setShape(const Shape & value) override;

View File

@ -31,6 +31,8 @@ Model * Model::getInstance(const char * name)
void ModelMesh::initMesh(const char * vert, const char * frag) void ModelMesh::initMesh(const char * vert, const char * frag)
{ {
initializeOpenGLFunctions();
// Create VAO, VBO, EBO // Create VAO, VBO, EBO
mVAO->create(); mVAO->create();
mVBO->create(); mVBO->create();
@ -173,7 +175,7 @@ void Model::flipTexture(const std::string & fileName, bool flipX, bool flipY)
texture.mTexture->destroy(); texture.mTexture->destroy();
texture.mTexture->create(); texture.mTexture->create();
texture.mTexture->setData( texture.mTexture->setData(
*Texture::initImage(fullPath.c_str(), flipX, flipY)); *OpenGLTextureFactory::initImage(fullPath.c_str(), flipX, flipY));
modified = true; modified = true;
} }
} }
@ -386,7 +388,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 = Texture::initTexture2D( texture.mTexture = OpenGLTextureFactory::initTexture2D(
std::string(mDirectory + '/' + fileName.C_Str()).c_str(), std::string(mDirectory + '/' + fileName.C_Str()).c_str(),
false, false); false, false);
texture.mID = texture.mTexture->textureId(); texture.mID = texture.mTexture->textureId();
@ -407,12 +409,13 @@ ModelMesh::Textures Model::loadMaterialTextures(
void Model::sortModels() void Model::sortModels()
{ {
auto cameraPos = Scene::Camera().transform(); auto cameraPos = Scene::Camera().transform();
auto cameraDistance = [&cameraPos](const ModelMesh &a, const ModelMesh &b) auto cameraDistance =
{ [&cameraPos](const ModelMesh &a, const ModelMesh &b)
// Sort by the first vertex position, since all transforms will be the same {
return (cameraPos.translation().distanceToPoint(a.mVertices[0].mPosition)) // Sort by the first vertex position in the model
< (cameraPos.translation().distanceToPoint(b.mVertices[0].mPosition)); return (cameraPos.getTranslation().distanceToPoint(a.mVertices[0].mPosition))
}; < (cameraPos.getTranslation().distanceToPoint(b.mVertices[0].mPosition));
};
std::sort(mMeshes.begin(), mMeshes.end(), cameraDistance); std::sort(mMeshes.begin(), mMeshes.end(), cameraDistance);
} }

View File

@ -16,6 +16,7 @@
#include <QOpenGLShaderProgram> #include <QOpenGLShaderProgram>
#include <QOpenGLTexture> #include <QOpenGLTexture>
#include <QOpenGLVertexArrayObject> #include <QOpenGLVertexArrayObject>
#include <QOpenGLFunctions>
// Assimp // Assimp
#include <assimp/Importer.hpp> #include <assimp/Importer.hpp>
@ -24,6 +25,7 @@
// QTK // QTK
#include <transform3D.h> #include <transform3D.h>
#include <object.h>
struct ModelVertex { struct ModelVertex {
@ -43,7 +45,7 @@ struct ModelTexture {
class Model; class Model;
class ModelMesh { class ModelMesh : protected QOpenGLFunctions {
public: public:
friend Model; friend Model;
typedef std::vector<ModelVertex> Vertices; typedef std::vector<ModelVertex> Vertices;

View File

@ -14,6 +14,7 @@
#include <QOpenGLVertexArrayObject> #include <QOpenGLVertexArrayObject>
#include <mesh.h> #include <mesh.h>
#include <texture.h>
class Object : public QObject { class Object : public QObject {
@ -32,19 +33,23 @@ public:
~Object() {} ~Object() {}
inline const Vertices & vertices() { return mShape.mVertices;} inline const Colors & getColors() { return mShape.mColors;}
inline const Indices & indices() { return mShape.mIndices;} inline const Indices & getIndexData() { return mShape.mIndices;}
inline const Colors & colors() { return mShape.mColors;} inline const Normals & getNormals() { return mShape.mNormals;}
inline const TexCoords & texCoords() { return mShape.mTexCoords;} inline const Shape & getShape() { return mShape;}
inline const Normals & normals() { return mShape.mNormals;} inline const TexCoords & getTexCoords() { return mShape.mTexCoords;}
inline QOpenGLTexture & texture() const { return *mTexture;} inline Texture & getTexture() { return mTexture;}
inline const Vertices & getVertices() { return mShape.mVertices;}
virtual inline void setVertices(const Vertices & value) { mShape.mVertices = value;}
virtual inline void setIndices(const Indices & value) { mShape.mIndices = value;}
virtual inline void setColors(const Colors & value) { mShape.mColors = value;} virtual inline void setColors(const Colors & value) { mShape.mColors = value;}
virtual inline void setTexCoords(const TexCoords & value) { mShape.mTexCoords = value;} virtual inline void setIndices(const Indices & value) { mShape.mIndices = value;}
virtual inline void setNormals(const Normals & value) { mShape.mNormals = value;} virtual inline void setNormals(const Normals & 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) { mShape.mTexCoords = value;}
virtual inline void setTexture(const char * path, bool flipX=false, bool flipY=false)
{ mTexture.setTexture(OpenGLTextureFactory::initTexture2D(path, flipX, flipY));}
virtual inline void setTexture(QOpenGLTexture * value) { mTexture.setTexture(value);}
virtual inline void setVertices(const Vertices & value) { mShape.mVertices = value;}
QOpenGLBuffer mVBO, mNBO; QOpenGLBuffer mVBO, mNBO;
QOpenGLVertexArrayObject mVAO; QOpenGLVertexArrayObject mVAO;
@ -52,10 +57,9 @@ public:
Transform3D mTransform; Transform3D mTransform;
Shape mShape; Shape mShape;
Texture mTexture;
const char * mName; const char * mName;
private:
QOpenGLTexture * mTexture;
}; };
#endif // QTK_OBJECT_H #endif // QTK_OBJECT_H

View File

@ -7,7 +7,18 @@
##############################################################################*/ ##############################################################################*/
#include "resourcemanager.h" #include "resourcemanager.h"
#include <algorithm>
#include <string>
#include <QtGlobal>
static std::string nixPath(std::string path)
{
#ifdef Q_OS_WINDOWS
std::replace(path.begin(), path.end(), '\\', '/');
#endif
return path;
}
std::string RM::resourcesDir = std::string RM::resourcesDir =
std::string(__FILE__).substr(0, std::string(__FILE__).find("src/")) std::string(__FILE__).substr(0, nixPath(__FILE__).find("src/"))
+ "resources/"; + "resources/";

View File

@ -24,10 +24,9 @@ public:
* Should be given in qrc format: ':/path/to/asset.obj' * Should be given in qrc format: ':/path/to/asset.obj'
* @return Absoulte system path to a qtk asset * @return Absoulte system path to a qtk asset
*/ */
static std::string getPath(const std::string & path) { static std::string getPath(const std::string & path)
// Only construct qtk resource path if in qrc format; else return it as-is // Only construct qtk resource path if in qrc format; else return it as-is
return path[0] == ':' ? resourcesDir + path.substr(2) : path; { return path[0] == ':' ? resourcesDir + path.substr(2) : path; }
}
static std::string resourcesDir; static std::string resourcesDir;
} RM; } RM;

View File

@ -64,12 +64,11 @@ void Scene::init()
mTestPhong->mNBO.create(); mTestPhong->mNBO.create();
mTestPhong->mNBO.setUsagePattern(QOpenGLBuffer::StaticDraw); mTestPhong->mNBO.setUsagePattern(QOpenGLBuffer::StaticDraw);
mTestPhong->mNBO.bind(); mTestPhong->mNBO.bind();
mTestPhong->mNBO.allocate(mTestPhong->normals().data(), mTestPhong->mNBO.allocate(mTestPhong->getNormals().data(),
mTestPhong->normals().size() mTestPhong->getNormals().size()
* sizeof(mTestPhong->normals()[0])); * sizeof(mTestPhong->getNormals()[0]));
mTestPhong->mProgram.enableAttributeArray(1); mTestPhong->mProgram.enableAttributeArray(1);
mTestPhong->mProgram.setAttributeBuffer(1, GL_FLOAT, 0, mTestPhong->mProgram.setAttributeBuffer(1, GL_FLOAT, 0, 3, sizeof(QVector3D));
3, sizeof(QVector3D));
mTestPhong->mNBO.release(); mTestPhong->mNBO.release();
mTestPhong->mVAO.release(); mTestPhong->mVAO.release();
mTestPhong->mProgram.release(); mTestPhong->mProgram.release();
@ -89,9 +88,9 @@ void Scene::init()
mTestAmbient->mNBO.create(); mTestAmbient->mNBO.create();
mTestAmbient->mNBO.setUsagePattern(QOpenGLBuffer::StaticDraw); mTestAmbient->mNBO.setUsagePattern(QOpenGLBuffer::StaticDraw);
mTestAmbient->mNBO.bind(); mTestAmbient->mNBO.bind();
mTestAmbient->mNBO.allocate(mTestAmbient->normals().data(), mTestAmbient->mNBO.allocate(mTestAmbient->getNormals().data(),
mTestAmbient->normals().size() mTestAmbient->getNormals().size()
* sizeof(mTestAmbient->normals()[0])); * sizeof(mTestAmbient->getNormals()[0]));
mTestAmbient->mProgram.enableAttributeArray(1); mTestAmbient->mProgram.enableAttributeArray(1);
mTestAmbient->mProgram.setAttributeBuffer(1, GL_FLOAT, 0, mTestAmbient->mProgram.setAttributeBuffer(1, GL_FLOAT, 0,
3, sizeof(QVector3D)); 3, sizeof(QVector3D));
@ -113,9 +112,9 @@ void Scene::init()
mTestDiffuse->mNBO.create(); mTestDiffuse->mNBO.create();
mTestDiffuse->mNBO.setUsagePattern(QOpenGLBuffer::StaticDraw); mTestDiffuse->mNBO.setUsagePattern(QOpenGLBuffer::StaticDraw);
mTestDiffuse->mNBO.bind(); mTestDiffuse->mNBO.bind();
mTestDiffuse->mNBO.allocate(mTestDiffuse->normals().data(), mTestDiffuse->mNBO.allocate(mTestDiffuse->getNormals().data(),
mTestDiffuse->normals().size() mTestDiffuse->getNormals().size()
* sizeof(mTestDiffuse->normals()[0])); * sizeof(mTestDiffuse->getNormals()[0]));
mTestDiffuse->mProgram.enableAttributeArray(1); mTestDiffuse->mProgram.enableAttributeArray(1);
mTestDiffuse->mProgram.setAttributeBuffer(1, GL_FLOAT, 0, mTestDiffuse->mProgram.setAttributeBuffer(1, GL_FLOAT, 0,
3, sizeof(QVector3D)); 3, sizeof(QVector3D));
@ -139,9 +138,9 @@ void Scene::init()
mTestSpecular->mNBO.create(); mTestSpecular->mNBO.create();
mTestSpecular->mNBO.setUsagePattern(QOpenGLBuffer::StaticDraw); mTestSpecular->mNBO.setUsagePattern(QOpenGLBuffer::StaticDraw);
mTestSpecular->mNBO.bind(); mTestSpecular->mNBO.bind();
mTestSpecular->mNBO.allocate(mTestSpecular->normals().data(), mTestSpecular->mNBO.allocate(mTestSpecular->getNormals().data(),
mTestSpecular->normals().size() mTestSpecular->getNormals().size()
* sizeof(mTestSpecular->normals()[0])); * sizeof(mTestSpecular->getNormals()[0]));
mTestSpecular->mProgram.enableAttributeArray(1); mTestSpecular->mProgram.enableAttributeArray(1);
mTestSpecular->mProgram.setAttributeBuffer(1, GL_FLOAT, 0, mTestSpecular->mProgram.setAttributeBuffer(1, GL_FLOAT, 0,
3, sizeof(QVector3D)); 3, sizeof(QVector3D));
@ -241,8 +240,7 @@ void Scene::init()
// Test basic cube with phong.vert and phong.frag shaders // Test basic cube with phong.vert and phong.frag shaders
mMeshes.push_back( mMeshes.push_back(new MeshRenderer("testLight", Triangle(QTK_DRAW_ELEMENTS)));
new MeshRenderer("testLight", Triangle(QTK_DRAW_ELEMENTS)));
mMeshes.back()->mTransform.setTranslation(5.0f, 1.25f, 10.0f); mMeshes.back()->mTransform.setTranslation(5.0f, 1.25f, 10.0f);
mMeshes.back()->mTransform.scale(0.25f); mMeshes.back()->mTransform.scale(0.25f);
mMeshes.back()->setDrawType(GL_LINE_LOOP); mMeshes.back()->setDrawType(GL_LINE_LOOP);
@ -250,8 +248,7 @@ void Scene::init()
mMeshes.back()->setColor(GREEN); mMeshes.back()->setColor(GREEN);
mMeshes.back()->init(); mMeshes.back()->init();
mMeshes.push_back( mMeshes.push_back(new MeshRenderer("testPhong", Cube(QTK_DRAW_ARRAYS)));
new MeshRenderer("testPhong", Cube(QTK_DRAW_ARRAYS)));
mMeshes.back()->mTransform.setTranslation(5.0f, 0.0f, 10.0f); mMeshes.back()->mTransform.setTranslation(5.0f, 0.0f, 10.0f);
mMeshes.back()->setShaders(":/phong.vert", ":/phong.frag"); mMeshes.back()->setShaders(":/phong.vert", ":/phong.frag");
mMeshes.back()->setColor(QVector3D(0.0f, 0.25f, 0.0f)); mMeshes.back()->setColor(QVector3D(0.0f, 0.25f, 0.0f));
@ -262,9 +259,9 @@ void Scene::init()
mMeshes.back()->mNBO.create(); mMeshes.back()->mNBO.create();
mMeshes.back()->mNBO.bind(); mMeshes.back()->mNBO.bind();
mMeshes.back()->mNBO.allocate(mMeshes.back()->normals().data(), mMeshes.back()->mNBO.allocate(mMeshes.back()->getNormals().data(),
mMeshes.back()->normals().size() mMeshes.back()->getNormals().size()
* sizeof(mMeshes.back()->normals()[0])); * sizeof(mMeshes.back()->getNormals()[0]));
mMeshes.back()->mProgram.enableAttributeArray(1); mMeshes.back()->mProgram.enableAttributeArray(1);
mMeshes.back()->mProgram.setAttributeBuffer(1, GL_FLOAT, 0, mMeshes.back()->mProgram.setAttributeBuffer(1, GL_FLOAT, 0,
3, sizeof(QVector3D)); 3, sizeof(QVector3D));
@ -294,8 +291,7 @@ void Scene::init()
new MeshRenderer("rightTriangle", Triangle(QTK_DRAW_ELEMENTS))); new MeshRenderer("rightTriangle", Triangle(QTK_DRAW_ELEMENTS)));
mMeshes.back()->mTransform.setTranslation(-5.0f, 0.0f, -2.0f); mMeshes.back()->mTransform.setTranslation(-5.0f, 0.0f, -2.0f);
mMeshes.push_back( mMeshes.push_back(new MeshRenderer("centerCube", Cube(QTK_DRAW_ELEMENTS)));
new MeshRenderer("centerCube", Cube(QTK_DRAW_ELEMENTS)));
mMeshes.back()->mTransform.setTranslation(-7.0f, 0.0f, -2.0f); mMeshes.back()->mTransform.setTranslation(-7.0f, 0.0f, -2.0f);
mMeshes.push_back( mMeshes.push_back(
@ -331,9 +327,9 @@ void Scene::init()
mMeshes.back()->mNBO.bind(); mMeshes.back()->mNBO.bind();
mMeshes.back()->mProgram.bind(); mMeshes.back()->mProgram.bind();
mMeshes.back()->mNBO.allocate(mMeshes.back()->normals().data(), mMeshes.back()->mNBO.allocate(mMeshes.back()->getNormals().data(),
mMeshes.back()->normals().size() mMeshes.back()->getNormals().size()
* sizeof(mMeshes.back()->normals()[0])); * sizeof(mMeshes.back()->getNormals()[0]));
mMeshes.back()->mProgram.enableAttributeArray(1); mMeshes.back()->mProgram.enableAttributeArray(1);
mMeshes.back()->mProgram.setAttributeBuffer(1, GL_FLOAT, 0, mMeshes.back()->mProgram.setAttributeBuffer(1, GL_FLOAT, 0,
3, sizeof(QVector3D)); 3, sizeof(QVector3D));
@ -344,7 +340,8 @@ void Scene::init()
// RGB Normals cube to show normals are correct with QTK_DRAW_ELEMENTS_NORMALS // RGB Normals cube to show normals are correct with QTK_DRAW_ELEMENTS_NORMALS
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("rgbNormalsCubeElementsTest", Cube(QTK_DRAW_ELEMENTS_NORMALS))); new MeshRenderer("rgbNormalsCubeElementsTest",
Cube(QTK_DRAW_ELEMENTS_NORMALS)));
mMeshes.back()->mTransform.setTranslation(5.0f, 0.0f, 2.0f); mMeshes.back()->mTransform.setTranslation(5.0f, 0.0f, 2.0f);
mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag"); mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag");
mMeshes.back()->init(); mMeshes.back()->init();
@ -353,9 +350,9 @@ void Scene::init()
mMeshes.back()->mNBO.bind(); mMeshes.back()->mNBO.bind();
mMeshes.back()->mProgram.bind(); mMeshes.back()->mProgram.bind();
mMeshes.back()->mNBO.allocate(mMeshes.back()->normals().data(), mMeshes.back()->mNBO.allocate(mMeshes.back()->getNormals().data(),
mMeshes.back()->normals().size() mMeshes.back()->getNormals().size()
* sizeof(mMeshes.back()->normals()[0])); * sizeof(mMeshes.back()->getNormals()[0]));
mMeshes.back()->mProgram.enableAttributeArray(1); mMeshes.back()->mProgram.enableAttributeArray(1);
mMeshes.back()->mProgram.setAttributeBuffer(1, GL_FLOAT, 0, mMeshes.back()->mProgram.setAttributeBuffer(1, GL_FLOAT, 0,
3, sizeof(QVector3D)); 3, sizeof(QVector3D));
@ -375,19 +372,16 @@ void Scene::init()
mMeshes.back()->init(); mMeshes.back()->init();
mMeshes.back()->mProgram.bind(); mMeshes.back()->mProgram.bind();
mMeshes.back()->setTexture(Texture::initTexture2D(":/crate.png")); mMeshes.back()->setTexture(OpenGLTextureFactory::initTexture2D(":/crate.png"));
mMeshes.back()->setUniform("uTexture", 0); mMeshes.back()->setUniform("uTexture", 0);
mMeshes.back()->texture().bind();
mMeshes.back()->texture().release();
mMeshes.back()->mVAO.bind(); mMeshes.back()->mVAO.bind();
mMeshes.back()->mNBO.destroy(); mMeshes.back()->mNBO.destroy();
mMeshes.back()->mNBO.create(); mMeshes.back()->mNBO.create();
mMeshes.back()->mNBO.bind(); mMeshes.back()->mNBO.bind();
mMeshes.back()->mNBO.allocate(mMeshes.back()->mShape.texCoords().data(), mMeshes.back()->mNBO.allocate(mMeshes.back()->mShape.getTexCoords().data(),
mMeshes.back()->mShape.texCoords().size() mMeshes.back()->mShape.getTexCoords().size()
* sizeof(mMeshes.back()->mShape.texCoords()[0])); * sizeof(mMeshes.back()->mShape.getTexCoords()[0]));
mMeshes.back()->mProgram.enableAttributeArray(1); mMeshes.back()->mProgram.enableAttributeArray(1);
mMeshes.back()->mProgram.setAttributeBuffer(1, GL_FLOAT, 0, mMeshes.back()->mProgram.setAttributeBuffer(1, GL_FLOAT, 0,
2, sizeof(QVector2D)); 2, sizeof(QVector2D));
@ -406,13 +400,13 @@ void Scene::init()
mMeshes.back()->mNBO.bind(); mMeshes.back()->mNBO.bind();
mMeshes.back()->mProgram.bind(); mMeshes.back()->mProgram.bind();
mMeshes.back()->mNBO.allocate(mMeshes.back()->texCoords().data(), mMeshes.back()->mNBO.allocate(mMeshes.back()->getTexCoords().data(),
mMeshes.back()->texCoords().size() mMeshes.back()->getTexCoords().size()
* sizeof(mMeshes.back()->texCoords()[0])); * sizeof(mMeshes.back()->getTexCoords()[0]));
mMeshes.back()->mProgram.enableAttributeArray(1); mMeshes.back()->mProgram.enableAttributeArray(1);
mMeshes.back()->mProgram.setAttributeBuffer(1, GL_FLOAT, 0, mMeshes.back()->mProgram.setAttributeBuffer(1, GL_FLOAT, 0,
3, sizeof(QVector3D)); 3, sizeof(QVector3D));
mMeshes.back()->setTexture(Texture::initTexture2D(":/crate.png")); mMeshes.back()->setTexture(OpenGLTextureFactory::initTexture2D(":/crate.png"));
mMeshes.back()->mProgram.setUniformValue("uTexture", 0); mMeshes.back()->mProgram.setUniformValue("uTexture", 0);
mMeshes.back()->mProgram.release(); mMeshes.back()->mProgram.release();
@ -430,16 +424,16 @@ void Scene::init()
mMeshes.back()->init(); mMeshes.back()->init();
mMeshes.back()->mProgram.bind(); mMeshes.back()->mProgram.bind();
mMeshes.back()->setTexture(Texture::initCubeMap(":/crate.png")); mMeshes.back()->setTexture(OpenGLTextureFactory::initCubeMap(":/crate.png"));
mMeshes.back()->setUniform("uTexture", 0); mMeshes.back()->setUniform("uTexture", 0);
mMeshes.back()->mVAO.bind(); mMeshes.back()->mVAO.bind();
mMeshes.back()->mNBO.destroy(); mMeshes.back()->mNBO.destroy();
mMeshes.back()->mNBO.create(); mMeshes.back()->mNBO.create();
mMeshes.back()->mNBO.bind(); mMeshes.back()->mNBO.bind();
mMeshes.back()->mNBO.allocate(mMeshes.back()->mShape.texCoords().data(), mMeshes.back()->mNBO.allocate(mMeshes.back()->mShape.getTexCoords().data(),
mMeshes.back()->mShape.texCoords().size() mMeshes.back()->mShape.getTexCoords().size()
* sizeof(mMeshes.back()->mShape.texCoords()[0])); * sizeof(mMeshes.back()->mShape.getTexCoords()[0]));
mMeshes.back()->mProgram.enableAttributeArray(1); mMeshes.back()->mProgram.enableAttributeArray(1);
mMeshes.back()->mProgram.setAttributeBuffer(1, GL_FLOAT, 0, mMeshes.back()->mProgram.setAttributeBuffer(1, GL_FLOAT, 0,
2, sizeof(QVector2D)); 2, sizeof(QVector2D));
@ -449,8 +443,7 @@ void Scene::init()
// Create a cube with custom shaders // Create a cube with custom shaders
// + Apply RGB normals shader and spin the cube for a neat effect // + Apply RGB normals shader and spin the cube for a neat effect
mMeshes.push_back( mMeshes.push_back(new MeshRenderer("rgbNormalsCube", Cube(QTK_DRAW_ARRAYS)));
new MeshRenderer("rgbNormalsCube", Cube(QTK_DRAW_ARRAYS)));
mMeshes.back()->mTransform.setTranslation(5.0f, 2.0f, -2.0f); mMeshes.back()->mTransform.setTranslation(5.0f, 2.0f, -2.0f);
mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag"); mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag");
mMeshes.back()->init(); mMeshes.back()->init();
@ -459,9 +452,9 @@ void Scene::init()
mMeshes.back()->mNBO.bind(); mMeshes.back()->mNBO.bind();
mMeshes.back()->mProgram.bind(); mMeshes.back()->mProgram.bind();
mMeshes.back()->mNBO.allocate(mMeshes.back()->normals().data(), mMeshes.back()->mNBO.allocate(mMeshes.back()->getNormals().data(),
mMeshes.back()->normals().size() mMeshes.back()->getNormals().size()
* sizeof(mMeshes.back()->normals()[0])); * sizeof(mMeshes.back()->getNormals()[0]));
mMeshes.back()->mProgram.enableAttributeArray(1); mMeshes.back()->mProgram.enableAttributeArray(1);
mMeshes.back()->mProgram.setAttributeBuffer(1, GL_FLOAT, 0, mMeshes.back()->mProgram.setAttributeBuffer(1, GL_FLOAT, 0,
3, sizeof(QVector3D)); 3, sizeof(QVector3D));
@ -481,9 +474,9 @@ void Scene::init()
mMeshes.back()->mVAO.bind(); mMeshes.back()->mVAO.bind();
mMeshes.back()->mNBO.create(); mMeshes.back()->mNBO.create();
mMeshes.back()->mNBO.bind(); mMeshes.back()->mNBO.bind();
mMeshes.back()->mNBO.allocate(mMeshes.back()->normals().data(), mMeshes.back()->mNBO.allocate(mMeshes.back()->getNormals().data(),
mMeshes.back()->normals().size() mMeshes.back()->getNormals().size()
* sizeof(mMeshes.back()->normals()[0])); * sizeof(mMeshes.back()->getNormals()[0]));
mMeshes.back()->mProgram.enableAttributeArray(1); mMeshes.back()->mProgram.enableAttributeArray(1);
mMeshes.back()->mProgram.setAttributeBuffer(1, GL_FLOAT, 0, mMeshes.back()->mProgram.setAttributeBuffer(1, GL_FLOAT, 0,
3, sizeof(QVector3D)); 3, sizeof(QVector3D));
@ -503,9 +496,9 @@ void Scene::init()
mMeshes.back()->mVAO.bind(); mMeshes.back()->mVAO.bind();
mMeshes.back()->mNBO.create(); mMeshes.back()->mNBO.create();
mMeshes.back()->mNBO.bind(); mMeshes.back()->mNBO.bind();
mMeshes.back()->mNBO.allocate(mMeshes.back()->normals().data(), mMeshes.back()->mNBO.allocate(mMeshes.back()->getNormals().data(),
mMeshes.back()->normals().size() mMeshes.back()->getNormals().size()
* sizeof(mMeshes.back()->normals()[0])); * sizeof(mMeshes.back()->getNormals()[0]));
mMeshes.back()->mProgram.enableAttributeArray(1); mMeshes.back()->mProgram.enableAttributeArray(1);
mMeshes.back()->mProgram.setAttributeBuffer(1, GL_FLOAT, 0, mMeshes.back()->mProgram.setAttributeBuffer(1, GL_FLOAT, 0,
3, sizeof(QVector3D)); 3, sizeof(QVector3D));
@ -521,19 +514,19 @@ void Scene::init()
mMeshes.back()->init(); mMeshes.back()->init();
mMeshes.back()->mProgram.bind(); mMeshes.back()->mProgram.bind();
mMeshes.back()->setTexture(Texture::initTexture2D(":/crate.png")); mMeshes.back()->setTexture(":/crate.png");
mMeshes.back()->setUniform("uTexture", 0);
mMeshes.back()->texture().bind();
mMeshes.back()->texture().release(); // Test assignment of Texture
mMeshes.back()->mTexture = Texture(":/crate.png");
mMeshes.back()->setUniform("uTexture", 0);
mMeshes.back()->mVAO.bind(); mMeshes.back()->mVAO.bind();
mMeshes.back()->mNBO.destroy(); mMeshes.back()->mNBO.destroy();
mMeshes.back()->mNBO.create(); mMeshes.back()->mNBO.create();
mMeshes.back()->mNBO.bind(); mMeshes.back()->mNBO.bind();
mMeshes.back()->mNBO.allocate(mMeshes.back()->mShape.texCoords().data(), mMeshes.back()->mNBO.allocate(mMeshes.back()->mShape.getTexCoords().data(),
mMeshes.back()->mShape.texCoords().size() mMeshes.back()->mShape.getTexCoords().size()
* sizeof(mMeshes.back()->mShape.texCoords()[0])); * sizeof(mMeshes.back()->mShape.getTexCoords()[0]));
mMeshes.back()->mProgram.enableAttributeArray(1); mMeshes.back()->mProgram.enableAttributeArray(1);
mMeshes.back()->mProgram.setAttributeBuffer(1, GL_FLOAT, 0, mMeshes.back()->mProgram.setAttributeBuffer(1, GL_FLOAT, 0,
2, sizeof(QVector2D)); 2, sizeof(QVector2D));
@ -550,19 +543,17 @@ void Scene::init()
mMeshes.back()->init(); mMeshes.back()->init();
mMeshes.back()->mProgram.bind(); mMeshes.back()->mProgram.bind();
mMeshes.back()->setTexture(Texture::initTexture2D(":/crate.png")); // mMeshes.back()->setTexture(OpenGLTextureFactory::initTexture2D(":/crate.png"));
mMeshes.back()->mTexture.setTexture(":/crate.png");
mMeshes.back()->setUniform("uTexture", 0); mMeshes.back()->setUniform("uTexture", 0);
mMeshes.back()->texture().bind();
mMeshes.back()->texture().release();
mMeshes.back()->mVAO.bind(); mMeshes.back()->mVAO.bind();
mMeshes.back()->mNBO.destroy(); mMeshes.back()->mNBO.destroy();
mMeshes.back()->mNBO.create(); mMeshes.back()->mNBO.create();
mMeshes.back()->mNBO.bind(); mMeshes.back()->mNBO.bind();
mMeshes.back()->mNBO.allocate(mMeshes.back()->mShape.texCoords().data(), mMeshes.back()->mNBO.allocate(mMeshes.back()->mShape.getTexCoords().data(),
mMeshes.back()->mShape.texCoords().size() mMeshes.back()->mShape.getTexCoords().size()
* sizeof(mMeshes.back()->mShape.texCoords()[0])); * sizeof(mMeshes.back()->mShape.getTexCoords()[0]));
mMeshes.back()->mProgram.enableAttributeArray(1); mMeshes.back()->mProgram.enableAttributeArray(1);
mMeshes.back()->mProgram.setAttributeBuffer(1, GL_FLOAT, 0, mMeshes.back()->mProgram.setAttributeBuffer(1, GL_FLOAT, 0,
2, sizeof(QVector2D)); 2, sizeof(QVector2D));
@ -605,24 +596,24 @@ void Scene::draw()
{ {
mSkybox.draw(); mSkybox.draw();
for (auto & model : mModels) model->draw(); for (const auto & model : mModels) model->draw();
for (const auto &mesh : mMeshes) mesh->draw(); for (const auto & mesh : mMeshes) mesh->draw();
mTestPhong->mProgram.bind(); mTestPhong->mProgram.bind();
mTestPhong->setUniform("uModelInverseTransposed", mTestPhong->setUniform("uModelInverseTransposed",
mTestPhong->mTransform.toMatrix().normalMatrix()); mTestPhong->mTransform.toMatrix().normalMatrix());
mTestPhong->setUniform( mTestPhong->setUniform(
"uLightPosition", "uLightPosition",
MeshRenderer::getInstance("phongLight")->mTransform.translation()); MeshRenderer::getInstance("phongLight")->mTransform.getTranslation());
mTestPhong->setUniform("uCameraPosition", mTestPhong->setUniform("uCameraPosition",
Scene::Camera().transform().translation()); Scene::Camera().transform().getTranslation());
mTestPhong->mProgram.release(); mTestPhong->mProgram.release();
mTestPhong->draw(); mTestPhong->draw();
mTestAmbient->mProgram.bind(); mTestAmbient->mProgram.bind();
mTestAmbient->setUniform("uCameraPosition", mTestAmbient->setUniform("uCameraPosition",
Scene::Camera().transform().translation()); Scene::Camera().transform().getTranslation());
mTestAmbient->mProgram.release(); mTestAmbient->mProgram.release();
mTestAmbient->draw(); mTestAmbient->draw();
@ -631,8 +622,9 @@ void Scene::draw()
mTestDiffuse->mTransform.toMatrix().normalMatrix()); mTestDiffuse->mTransform.toMatrix().normalMatrix());
mTestDiffuse->setUniform( mTestDiffuse->setUniform(
"uLightPosition", "uLightPosition",
MeshRenderer::getInstance("diffuseLight")->mTransform.translation()); MeshRenderer::getInstance("diffuseLight")->mTransform.getTranslation());
mTestDiffuse->setUniform("uCameraPosition", Scene::Camera().transform().translation()); mTestDiffuse->setUniform("uCameraPosition",
Scene::Camera().transform().getTranslation());
mTestDiffuse->mProgram.release(); mTestDiffuse->mProgram.release();
mTestDiffuse->draw(); mTestDiffuse->draw();
@ -642,19 +634,21 @@ void Scene::draw()
mTestSpecular->mTransform.toMatrix().normalMatrix()); mTestSpecular->mTransform.toMatrix().normalMatrix());
mTestSpecular->setUniform( mTestSpecular->setUniform(
"uLightPosition", "uLightPosition",
MeshRenderer::getInstance("specularLight")->mTransform.translation()); MeshRenderer::getInstance("specularLight")->mTransform.getTranslation());
mTestSpecular->setUniform("uCameraPosition", Scene::Camera().transform().translation()); mTestSpecular->setUniform("uCameraPosition",
Scene::Camera().transform().getTranslation());
mTestSpecular->mProgram.release(); mTestSpecular->mProgram.release();
mTestSpecular->draw(); mTestSpecular->draw();
} }
void Scene::update() void Scene::update()
{ {
auto position = MeshRenderer::getInstance("alienTestLight")->mTransform.translation(); auto position = MeshRenderer::getInstance(
"alienTestLight")->mTransform.getTranslation();
Model::getInstance("alienTest")->setUniform( Model::getInstance("alienTest")->setUniform(
"uLight.position", position); "uLight.position", position);
Model::getInstance("alienTest")->setUniform( Model::getInstance("alienTest")->setUniform(
"uCameraPosition", Scene::Camera().transform().translation()); "uCameraPosition", Scene::Camera().transform().getTranslation());
auto posMatrix = Model::getInstance("alienTest")->mTransform.toMatrix(); auto posMatrix = Model::getInstance("alienTest")->mTransform.toMatrix();
Model::getInstance("alienTest")->setUniform( Model::getInstance("alienTest")->setUniform(
"uMVP.normalMatrix", posMatrix.normalMatrix()); "uMVP.normalMatrix", posMatrix.normalMatrix());
@ -666,11 +660,12 @@ void Scene::update()
"uMVP.projection", Scene::Projection()); "uMVP.projection", Scene::Projection());
Model::getInstance("alienTest")->mTransform.rotate(0.75f, 0.0f, 1.0f, 0.0f); Model::getInstance("alienTest")->mTransform.rotate(0.75f, 0.0f, 1.0f, 0.0f);
position = MeshRenderer::getInstance("spartanTestLight")->mTransform.translation(); position = MeshRenderer::getInstance(
"spartanTestLight")->mTransform.getTranslation();
Model::getInstance("spartanTest")->setUniform( Model::getInstance("spartanTest")->setUniform(
"uLight.position", position); "uLight.position", position);
Model::getInstance("spartanTest")->setUniform( Model::getInstance("spartanTest")->setUniform(
"uCameraPosition", Scene::Camera().transform().translation()); "uCameraPosition", Scene::Camera().transform().getTranslation());
posMatrix = Model::getInstance("spartanTest")->mTransform.toMatrix(); posMatrix = Model::getInstance("spartanTest")->mTransform.toMatrix();
Model::getInstance("spartanTest")->setUniform( Model::getInstance("spartanTest")->setUniform(
"uMVP.normalMatrix", posMatrix.normalMatrix()); "uMVP.normalMatrix", posMatrix.normalMatrix());
@ -687,11 +682,11 @@ void Scene::update()
MeshRenderer::getInstance("testPhong")->mTransform.rotate( MeshRenderer::getInstance("testPhong")->mTransform.rotate(
0.75f, 1.0f, 0.5f, 0.0f); 0.75f, 1.0f, 0.5f, 0.0f);
MeshRenderer::getInstance("testPhong")->mProgram.bind(); MeshRenderer::getInstance("testPhong")->mProgram.bind();
position = MeshRenderer::getInstance("testLight")->mTransform.translation(); position = MeshRenderer::getInstance("testLight")->mTransform.getTranslation();
MeshRenderer::getInstance("testPhong")->setUniform( MeshRenderer::getInstance("testPhong")->setUniform(
"uLight.position", position); "uLight.position", position);
MeshRenderer::getInstance("testPhong")->setUniform( MeshRenderer::getInstance("testPhong")->setUniform(
"uCameraPosition", Scene::Camera().transform().translation()); "uCameraPosition", Scene::Camera().transform().getTranslation());
posMatrix = MeshRenderer::getInstance("testPhong")->mTransform.toMatrix(); posMatrix = MeshRenderer::getInstance("testPhong")->mTransform.toMatrix();
MeshRenderer::getInstance("testPhong")->setUniform( MeshRenderer::getInstance("testPhong")->setUniform(
"uMVP.normalMatrix", posMatrix.normalMatrix()); "uMVP.normalMatrix", posMatrix.normalMatrix());
@ -727,7 +722,7 @@ void Scene::update()
static float translateX = 0.025f; static float translateX = 0.025f;
float limit = -9.0f; // Origin position.x - 2.0f float limit = -9.0f; // Origin position.x - 2.0f
float posX = float posX =
MeshRenderer::getInstance("topTriangle")->mTransform.translation().x(); MeshRenderer::getInstance("topTriangle")->mTransform.getTranslation().x();
if (posX < limit || posX > limit + 4.0f) { if (posX < limit || posX > limit + 4.0f) {
translateX = -translateX; translateX = -translateX;
} }

View File

@ -15,13 +15,13 @@
Skybox::Skybox(std::string right, std::string top, std::string front, Skybox::Skybox(std::string right, std::string top, std::string front,
std::string left, std::string bottom, std::string back, std::string left, std::string bottom, std::string back,
const std::string & name) const std::string & name)
: mCubeMap(Texture::initCubeMap( : mCubeMap(OpenGLTextureFactory::initCubeMap(
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(back.c_str()))), QImage(bottom.c_str()), QImage(back.c_str()))),
mVBO(QOpenGLBuffer::VertexBuffer), mVBO(QOpenGLBuffer::VertexBuffer),
mVertices(Cube(QTK_DRAW_ELEMENTS).vertices()), mVertices(Cube(QTK_DRAW_ELEMENTS).getVertices()),
mIndices(Cube(QTK_DRAW_ELEMENTS).indices()) mIndices(Cube(QTK_DRAW_ELEMENTS).getIndexData())
{ init();} { init();}
Skybox::Skybox(std::string name) Skybox::Skybox(std::string name)
@ -69,6 +69,8 @@ void Skybox::draw()
void Skybox::init() void Skybox::init()
{ {
initializeOpenGLFunctions();
// Set up shader program // Set up shader program
mProgram.create(); mProgram.create();
mProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/skybox.vert"); mProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/skybox.vert");

View File

@ -13,12 +13,13 @@
#include <QOpenGLShaderProgram> #include <QOpenGLShaderProgram>
#include <QOpenGLTexture> #include <QOpenGLTexture>
#include <QOpenGLVertexArrayObject> #include <QOpenGLVertexArrayObject>
#include <QOpenGLFunctions>
#include <camera3d.h> #include <camera3d.h>
#include <mesh.h> #include <mesh.h>
class Skybox { class Skybox : protected QOpenGLFunctions {
public: public:
// Delegate this constructor to use default skybox images // Delegate this constructor to use default skybox images
// + This allows creating a skybox with no arguments ( auto s = new Skybox; ) // + This allows creating a skybox with no arguments ( auto s = new Skybox; )

View File

@ -11,8 +11,9 @@
#include <texture.h> #include <texture.h>
std::unordered_map<std::string, Texture *> TM::textureMap;
QImage * Texture::initImage(const char * image, bool flipX, bool flipY) QImage * OpenGLTextureFactory::initImage(const char * image, bool flipX, bool flipY)
{ {
// Qt6 limits loaded images to 256MB by default // Qt6 limits loaded images to 256MB by default
QImageReader::setAllocationLimit(512); QImageReader::setAllocationLimit(512);
@ -26,8 +27,8 @@ QImage * Texture::initImage(const char * image, bool flipX, bool flipY)
return loadedImage; return loadedImage;
} }
QOpenGLTexture * Texture::initTexture2D(const char * texture, QOpenGLTexture * OpenGLTextureFactory::initTexture2D(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);
@ -39,14 +40,14 @@ QOpenGLTexture * Texture::initTexture2D(const char * texture,
return newTexture; return newTexture;
} }
QOpenGLTexture * Texture::initCubeMap(const char * tile) QOpenGLTexture * OpenGLTextureFactory::initCubeMap(const char * tile)
{ {
return initCubeMap(QImage(tile), QImage(tile), return initCubeMap(QImage(tile), QImage(tile),
QImage(tile), QImage(tile), QImage(tile), QImage(tile),
QImage(tile), QImage(tile)); QImage(tile), QImage(tile));
} }
QOpenGLTexture * Texture::initCubeMap( QOpenGLTexture * OpenGLTextureFactory::initCubeMap(
const char * right, const char * top, const char * right, const char * top,
const char * front, const char * left, const char * front, const char * left,
const char * bottom, const char * back) const char * bottom, const char * back)
@ -56,7 +57,7 @@ QOpenGLTexture * Texture::initCubeMap(
QImage(bottom), QImage(back)); QImage(bottom), QImage(back));
} }
QOpenGLTexture * Texture::initCubeMap( QOpenGLTexture * OpenGLTextureFactory::initCubeMap(
QImage right, QImage top, QImage right, QImage top,
QImage front, QImage left, QImage front, QImage left,
QImage bottom, QImage back) QImage bottom, QImage back)

View File

@ -11,10 +11,9 @@
#include <QOpenGLTexture> #include <QOpenGLTexture>
class OpenGLTextureFactory {
class Texture {
public: public:
~Texture() {} ~OpenGLTextureFactory() = default;
// QImage // QImage
static QImage * initImage(const char * image, static QImage * initImage(const char * image,
@ -36,7 +35,57 @@ public:
private: private:
// Private ctor to prevent creating instances of this class // Private ctor to prevent creating instances of this class
Texture() {} OpenGLTextureFactory() = default;
};
class Texture;
typedef class TextureManager {
public:
static inline Texture * getInstance(std::string path)
{ return textureMap.count(path) > 0 ? textureMap[path] : Q_NULLPTR; }
static inline bool addInstance(const std::string & path, Texture * texture)
{ return textureMap.emplace(path, texture).second ? true : false; }
private:
static std::unordered_map<std::string, Texture *> textureMap;
} TM;
class Texture {
// explicit Texture(QOpenGLTexture * texture) : mOpenGLTexture(texture) { }
public:
Texture() = default;
Texture(const Texture & value) {
if (TM::getInstance(value.mPath)) {
mOpenGLTexture = TM::getInstance(value.mPath)->mOpenGLTexture;
}
else {
mOpenGLTexture = OpenGLTextureFactory::initTexture2D(value.mPath);
TM::addInstance(value.mPath, this);
}
mPath = value.mPath;
}
explicit Texture(const char * path, bool flipX=false, bool flipY=false) :
mPath(path) {
if (TM::getInstance(path) == Q_NULLPTR) {
mOpenGLTexture = OpenGLTextureFactory::initTexture2D(path, flipX, flipY);
TM::addInstance(path, this);
}
else {
mOpenGLTexture = TM::getInstance(path)->mOpenGLTexture;
}
}
// ~Texture() { if (mOpenGLTexture) mOpenGLTexture->destroy();}
inline QOpenGLTexture & getOpenGLTexture() { return *mOpenGLTexture;}
inline void setTexture(const char * path, bool flipX=false, bool flipY=false)
{ mOpenGLTexture = OpenGLTextureFactory::initTexture2D(path, flipX, flipY);}
inline void setTexture(QOpenGLTexture * texture) { mOpenGLTexture = texture;}
inline bool hasTexture() const { return mOpenGLTexture != Q_NULLPTR;}
QOpenGLTexture * mOpenGLTexture = Q_NULLPTR;
const char * mPath;
}; };
#endif // QTOPENGL_TEXTURE_H #endif // QTOPENGL_TEXTURE_H

View File

@ -90,17 +90,17 @@ const QMatrix4x4 & Transform3D::toMatrix()
* Queries * Queries
******************************************************************************/ ******************************************************************************/
QVector3D Transform3D::forward() const QVector3D Transform3D::getForward() const
{ {
return mRotation.rotatedVector(LocalForward); return mRotation.rotatedVector(LocalForward);
} }
QVector3D Transform3D::up() const QVector3D Transform3D::getUp() const
{ {
return mRotation.rotatedVector(LocalUp); return mRotation.rotatedVector(LocalUp);
} }
QVector3D Transform3D::right() const QVector3D Transform3D::getRight() const
{ {
return mRotation.rotatedVector(LocalRight); return mRotation.rotatedVector(LocalRight);
} }
@ -113,16 +113,16 @@ QVector3D Transform3D::right() const
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.translation().x() << ", " dbg << "Position: <" << transform.getTranslation().x() << ", "
<< transform.translation().y() << ", " << transform.getTranslation().y() << ", "
<< transform.translation().z() << ">\n"; << transform.getTranslation().z() << ">\n";
dbg << "Scale: <" << transform.scale().x() << ", " dbg << "Scale: <" << transform.getScale().x() << ", "
<< transform.scale().y() << ", " << transform.getScale().y() << ", "
<< transform.scale().z() << ">\n"; << transform.getScale().z() << ">\n";
dbg << "Rotation: <" << transform.rotation().x() << ", " dbg << "Rotation: <" << transform.getRotation().x() << ", "
<< transform.rotation().y() << ", " << transform.getRotation().y() << ", "
<< transform.rotation().z() << " | " << << transform.getRotation().z() << " | " <<
transform.rotation().scalar() << ">\n}"; transform.getRotation().scalar() << ">\n}";
return dbg; return dbg;
} }

View File

@ -77,14 +77,14 @@ public:
// //
// Accessors // Accessors
inline const QVector3D & translation() const { return mTranslation;} inline const QVector3D & getTranslation() const { return mTranslation;}
inline const QVector3D & scale() const { return mScale; } inline const QVector3D & getScale() const { return mScale; }
inline const QQuaternion & rotation() const { return mRotation; } inline const QQuaternion & getRotation() const { return mRotation; }
const QMatrix4x4 & toMatrix(); const QMatrix4x4 & toMatrix();
QVector3D forward() const; QVector3D getForward() const;
QVector3D up() const; QVector3D getUp() const;
QVector3D right() const; QVector3D getRight() const;
static const QVector3D LocalForward, LocalUp, LocalRight; static const QVector3D LocalForward, LocalUp, LocalRight;