Compare commits

...

3 Commits

Author SHA1 Message Date
Shaun Reed ebb597dae6 Work on Texture class 2022-07-31 19:22:49 -04:00
Shaun Reed ab60994203 Refactor 2022-07-31 19:22:49 -04:00
Shaun Reed c15d064dce Add ResourceManager for assets outside of QRC
+ Use qt6_add_big_resources to improve build time
+ RM::getPath(sting) to build absolute path to assets
+ Allows easy access to models or other large assets not loaded into QRC
2022-07-31 19:13:54 -04:00
21 changed files with 298 additions and 233 deletions

View File

@ -20,17 +20,18 @@ set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
# For CLion builds, point CMAKE_PREFIX_PATH to Qt6 install directory # For CLion builds, point CMAKE_PREFIX_PATH to Qt6 install directory
list(APPEND CMAKE_PREFIX_PATH $ENV{HOME}/Code/Clones/Qt6.2/6.2.3/gcc_64/) list(APPEND CMAKE_PREFIX_PATH $ENV{HOME}/Code/Clones/Qt/6.3.1/gcc_64/)
find_package(Qt6 COMPONENTS OpenGLWidgets REQUIRED) find_package(Qt6 COMPONENTS OpenGLWidgets)
if (NOT Qt6_FOUND)
message(SEND_ERROR "Unable to find Qt6 at CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}")
message(FATAL_ERROR "Specify path to Qt6 with `cmake -DCMAKE_PREFIX_PATH=/path/to/Qt/6.x.x/gcc_64 -S /path/to/qtk -B /path/to/qtk/build && cmake --build /path/to/qtk/build -j $(nprocs)`")
endif()
# Add our Qt resources.qrc file to our application # Add our Qt resources.qrc file to our application
set(SOURCES app/main.cpp) set(SOURCES app/main.cpp)
qt6_add_resources(SOURCES resources.qrc) qt6_add_big_resources(SOURCES resources.qrc)
add_executable( add_executable(qtk ${SOURCES})
qtk # Executable name
${SOURCES} # Executable source code
)
################################################################################ ################################################################################
# External Libraries # External Libraries
@ -59,6 +60,7 @@ add_library(main-widget SHARED
src/transform3D.cpp src/transform3D.h src/transform3D.cpp src/transform3D.h
src/model.cpp src/model.h src/model.cpp src/model.h
src/scene.cpp src/scene.h src/scene.cpp src/scene.h
src/resourcemanager.cpp src/resourcemanager.h
) )
target_include_directories(main-widget PUBLIC src/) target_include_directories(main-widget PUBLIC src/)

View File

@ -23,10 +23,9 @@ Be sure to take note of the Qt6 installation directory, as we will need it to co
Once Qt6 is installed, to build and run `qtk` on Ubuntu - Once Qt6 is installed, to build and run `qtk` on Ubuntu -
```bash ```bash
sudo apt update -y && sudo apt install freeglut3-dev libassimp-dev cmake build-essential git sudo apt update -y && sudo apt install freeglut3-dev libassimp-dev cmake build-essential git
git clone https://gitlab.com/shaunrd0/qtk && cd qtk git clone https://gitlab.com/shaunrd0/qtk
mkdir build && cd build cmake -DCMAKE_PREFIX_PATH=$HOME/Qt/6.3.1/gcc_64 -S qtk/ -B qtk/build/ && cmake --build qtk/build/ -j $(nprocs)
cmake .. -DCMAKE_PREFIX_PATH=$HOME/Qt6/6.2.3/gcc_64 && cmake --build . ./qtk/build/qtk
./qtk
``` ```
You can fly around the scene if you hold the right mouse button and use WASD. You can fly around the scene if you hold the right mouse button and use WASD.

View File

@ -9,8 +9,8 @@
#include <QApplication> #include <QApplication>
#include <QLabel> #include <QLabel>
#include <mainwidget.h>
#include <mainwindow.h> #include <mainwindow.h>
#include <QSurfaceFormat>
int main(int argc, char *argv[]) int main(int argc, char *argv[])

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
@ -37,7 +39,8 @@ public:
// Shader settings // Shader settings
inline void setShaderVertex(const std::string & vert) { mVertexShader = vert;} inline void setShaderVertex(const std::string & vert) { mVertexShader = vert;}
inline void setShaderFragment(const std::string & frag) { mFragmentShader = frag;} inline void setShaderFragment(const std::string & frag)
{ mFragmentShader = frag;}
void setShaders(const std::string & vert, const std::string & frag); void setShaders(const std::string & vert, const std::string & frag);
template <typename T> template <typename T>
@ -53,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

@ -11,6 +11,7 @@
#include <scene.h> #include <scene.h>
#include <texture.h> #include <texture.h>
#include <resourcemanager.h>
#include <model.h> #include <model.h>
@ -172,7 +173,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;
} }
} }
@ -188,6 +189,21 @@ void Model::flipTexture(const std::string & fileName, bool flipX, bool flipY)
* Model Private Member Functions * Model Private Member Functions
******************************************************************************/ ******************************************************************************/
/**
* Loads a model in .obj, .fbx, .gltf, and other formats
* For a full list of formats see assimp documentation:
* https://github.com/assimp/assimp/blob/master/doc/Fileformats.md
*
* Models should not be loaded into Qt resource system
* Instead pass an *absolute* path to this function
* Relative paths will break if Qtk is executed from different locations
*
* Models can also be loaded from the `qtk/resource` directory using qrc format
* loadModel(":/models/backpack/backpack.obj")
* See resourcemanager.h for more information
*
* @param path Absolute path to a model .obj or other format accepted by assimp
*/
void Model::loadModel(const std::string & path) void Model::loadModel(const std::string & path)
{ {
Assimp::Importer import; Assimp::Importer import;
@ -195,13 +211,14 @@ void Model::loadModel(const std::string & path)
// JIC a relative path was used, get the absolute file path // JIC a relative path was used, get the absolute file path
QFileInfo info(path.c_str()); QFileInfo info(path.c_str());
info.makeAbsolute(); info.makeAbsolute();
std::string temp = info.absoluteFilePath().toStdString(); mDirectory = path[0] == ':' ? RM::getPath(path)
: info.absoluteFilePath().toStdString();
// Import the model, converting non-triangular geometry to triangles // Import the model, converting non-triangular geometry to triangles
// + And flipping texture UVs, etc.. // + And flipping texture UVs, etc..
// Assimp options: http://assimp.sourceforge.net/lib_html/postprocess_8h.html // Assimp options: http://assimp.sourceforge.net/lib_html/postprocess_8h.html
const aiScene * scene = const aiScene * scene =
import.ReadFile(temp, aiProcess_Triangulate import.ReadFile(mDirectory, aiProcess_Triangulate
| aiProcess_FlipUVs | aiProcess_FlipUVs
| aiProcess_GenSmoothNormals | aiProcess_GenSmoothNormals
| aiProcess_CalcTangentSpace | aiProcess_CalcTangentSpace
@ -216,7 +233,7 @@ void Model::loadModel(const std::string & path)
return; return;
} }
// If there were no errors, find the directory that contains this model // If there were no errors, find the directory that contains this model
mDirectory = path.substr(0, path.find_last_of('/')); mDirectory = mDirectory.substr(0, mDirectory.find_last_of('/'));
// Pass the pointers to the root node and the scene to recursive function // Pass the pointers to the root node and the scene to recursive function
// + Base case breaks when no nodes left to process on model // + Base case breaks when no nodes left to process on model
@ -369,7 +386,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();
@ -390,11 +407,12 @@ 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 // Sort by the first vertex position in the model
return (cameraPos.translation().distanceToPoint(a.mVertices[0].mPosition)) return (cameraPos.getTranslation().distanceToPoint(a.mVertices[0].mPosition))
< (cameraPos.translation().distanceToPoint(b.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

@ -24,6 +24,7 @@
// QTK // QTK
#include <transform3D.h> #include <transform3D.h>
#include <object.h>
struct ModelVertex { struct ModelVertex {

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

13
src/resourcemanager.cpp Normal file
View File

@ -0,0 +1,13 @@
/*##############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ##
## About: Manage files and resources used by qtk ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################*/
#include "resourcemanager.h"
std::string RM::resourcesDir =
std::string(__FILE__).substr(0, std::string(__FILE__).find("src/"))
+ "resources/";

35
src/resourcemanager.h Normal file
View File

@ -0,0 +1,35 @@
/*##############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ##
## About: Manage files and resources used by qtk ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################*/
#include <string>
#ifndef QTK_RESOURCEMANAGER_H
#define QTK_RESOURCEMANAGER_H
typedef class ResourceManager {
public:
/**
* Takes a path using qrc format and constructs full system path to qtk assets
* Qrc format prefix ':/' is trimmed from the path for the caller
* Assets used with RM may (or may not) appear in qtk/resources.qrc
*
* @param path Path relative to qtk/resources/; ie) ':/models/backpack/backpack.obj'
* An asset at location qtk/resources/path/to/asset.obj
* Should be given in qrc format: ':/path/to/asset.obj'
* @return Absoulte system path to a qtk asset
*/
static std::string getPath(const std::string & path) {
// Only construct qtk resource path if in qrc format; else return it as-is
return path[0] == ':' ? resourcesDir + path.substr(2) : path;
}
static std::string resourcesDir;
} RM;
#endif //QTK_RESOURCEMANAGER_H

View File

@ -10,6 +10,7 @@
#include <texture.h> #include <texture.h>
#include <meshrenderer.h> #include <meshrenderer.h>
#include <model.h> #include <model.h>
#include <resourcemanager.h>
#include <scene.h> #include <scene.h>
@ -63,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();
@ -88,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));
@ -112,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));
@ -138,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));
@ -151,42 +151,31 @@ void Scene::init()
// //
// Model loading // Model loading
mModels.push_back(new Model("backpack", mModels.push_back(new Model("backpack", ":/models/backpack/backpack.obj"));
"../resources/models/backpack/backpack.obj"));
// Sometimes model textures need flipped in certain directions // Sometimes model textures need flipped in certain directions
mModels.back()->flipTexture("diffuse.jpg", false, true); mModels.back()->flipTexture("diffuse.jpg", false, true);
mModels.back()->mTransform.setTranslation(0.0f, 0.0f, -10.0f); mModels.back()->mTransform.setTranslation(0.0f, 0.0f, -10.0f);
mModels.push_back( mModels.push_back(new Model("bird", ":/models/bird/bird.obj"));
new Model("bird",
"../resources/models/bird/bird.obj"));
mModels.back()->mTransform.setTranslation(2.0f, 2.0f, -10.0f); mModels.back()->mTransform.setTranslation(2.0f, 2.0f, -10.0f);
// Sometimes the models are very large // Sometimes the models are very large
mModels.back()->mTransform.scale(0.0025f); mModels.back()->mTransform.scale(0.0025f);
mModels.back()->mTransform.rotate(-110.0f, 0.0f, 1.0f, 0.0f); mModels.back()->mTransform.rotate(-110.0f, 0.0f, 1.0f, 0.0f);
mModels.push_back(new Model("lion", mModels.push_back(new Model("lion", ":/models/lion/lion.obj"));
"../resources/models/lion/lion.obj"));
mModels.back()->mTransform.setTranslation(-3.0f, -1.0f, -10.0f); mModels.back()->mTransform.setTranslation(-3.0f, -1.0f, -10.0f);
mModels.back()->mTransform.scale(0.15f); mModels.back()->mTransform.scale(0.15f);
mModels.push_back( mModels.push_back(new Model("alien", ":/models/alien-hominid/alien.obj"));
new Model("alien",
"../resources/models/alien-hominid/alien.obj"));
mModels.back()->mTransform.setTranslation(2.0f, -1.0f, -5.0f); mModels.back()->mTransform.setTranslation(2.0f, -1.0f, -5.0f);
mModels.back()->mTransform.scale(0.15f); mModels.back()->mTransform.scale(0.15f);
mModels.push_back( mModels.push_back(new Model("scythe", ":/models/scythe/scythe.obj"));
new Model("scythe",
"../resources/models/scythe/scythe.obj")
);
mModels.back()->mTransform.setTranslation(-6.0f, 0.0f, -10.0f); mModels.back()->mTransform.setTranslation(-6.0f, 0.0f, -10.0f);
mModels.back()->mTransform.rotate(-90.0f, 1.0f, 0.0f, 0.0f); mModels.back()->mTransform.rotate(-90.0f, 1.0f, 0.0f, 0.0f);
mModels.back()->mTransform.rotate(90.0f, 0.0f, 1.0f, 0.0f); mModels.back()->mTransform.rotate(90.0f, 0.0f, 1.0f, 0.0f);
mModels.push_back( mModels.push_back(new Model("masterChief", ":/models/spartan/spartan.obj"));
new Model("masterChief",
"../resources/models/spartan/spartan.obj"));
mModels.back()->mTransform.setTranslation(-1.5f, 0.5f, -2.0f); mModels.back()->mTransform.setTranslation(-1.5f, 0.5f, -2.0f);
@ -204,9 +193,9 @@ void Scene::init()
mMeshes.back()->init(); mMeshes.back()->init();
mModels.push_back( mModels.push_back(
new Model("alienTest", new Model("alienTest", ":/models/alien-hominid/alien.obj",
"../resources/models/alien-hominid/alien.obj", ":/model-specular.vert", ":/model-specular.frag")
":/model-specular.vert", ":/model-specular.frag")); );
mModels.back()->mTransform.setTranslation(3.0f, -1.0f, 10.0f); mModels.back()->mTransform.setTranslation(3.0f, -1.0f, 10.0f);
mModels.back()->mTransform.scale(0.15f); mModels.back()->mTransform.scale(0.15f);
mModels.back()->setUniform("uMaterial.ambient", QVector3D(1.0f, 1.0f, 1.0f)); mModels.back()->setUniform("uMaterial.ambient", QVector3D(1.0f, 1.0f, 1.0f));
@ -224,7 +213,8 @@ void Scene::init()
// Test spartan Model with phong lighting, specular and normal mapping // Test spartan Model with phong lighting, specular and normal mapping
mMeshes.push_back( mMeshes.push_back(
new MeshRenderer("spartanTestLight", Triangle(QTK_DRAW_ELEMENTS))); new MeshRenderer("spartanTestLight", Triangle(QTK_DRAW_ELEMENTS))
);
mMeshes.back()->mTransform.setTranslation(1.0f, 1.5f, 10.0f); mMeshes.back()->mTransform.setTranslation(1.0f, 1.5f, 10.0f);
mMeshes.back()->mTransform.scale(0.25f); mMeshes.back()->mTransform.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
@ -232,9 +222,9 @@ void Scene::init()
mMeshes.back()->init(); mMeshes.back()->init();
mModels.push_back( mModels.push_back(
new Model("spartanTest", new Model("spartanTest", ":/models/spartan/spartan.obj",
"../resources/models/spartan/spartan.obj", ":/model-normals.vert", ":/model-normals.frag")
":/model-normals.vert", ":/model-normals.frag")); );
mModels.back()->mTransform.setTranslation(0.0f, -1.0f, 10.0f); mModels.back()->mTransform.setTranslation(0.0f, -1.0f, 10.0f);
mModels.back()->mTransform.scale(2.0f); mModels.back()->mTransform.scale(2.0f);
mModels.back()->setUniform("uMaterial.ambient", QVector3D(1.0f, 1.0f, 1.0f)); mModels.back()->setUniform("uMaterial.ambient", QVector3D(1.0f, 1.0f, 1.0f));
@ -250,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);
@ -259,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));
@ -271,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));
@ -303,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(
@ -340,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));
@ -353,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();
@ -362,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));
@ -384,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));
@ -415,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();
@ -439,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));
@ -458,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();
@ -468,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));
@ -490,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));
@ -512,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));
@ -530,19 +514,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(":/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));
@ -559,19 +540,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));
@ -614,24 +593,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();
@ -640,8 +619,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();
@ -651,19 +631,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());
@ -675,11 +657,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());
@ -696,11 +679,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());
@ -736,7 +719,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)

View File

@ -11,8 +11,7 @@
#include <texture.h> #include <texture.h>
QImage * OpenGLTextureFactory::initImage(const char * image, bool flipX, bool flipY)
QImage * Texture::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,7 +25,7 @@ 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);
@ -39,14 +38,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 +55,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,34 @@ 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 {
public:
Texture() = default;
Texture(const Texture & value) = delete;
// Texture(const Texture & value) {
// mOpenGLTexture = OpenGLTextureFactory::initTexture2D(value.mPath);
// mPath = value.mPath;
// }
explicit Texture(const char * path, bool flipX=false, bool flipY=false) :
mOpenGLTexture(OpenGLTextureFactory::initTexture2D(path, flipX, flipY)),
mPath(path) { }
// explicit Texture(QOpenGLTexture * texture) : mOpenGLTexture(texture) { }
~Texture() { mOpenGLTexture->destroy();}
inline QOpenGLTexture & getOpenGLTexture() { return *mOpenGLTexture;}
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;