Doxygen comments
This commit was merged in pull request #12.
This commit is contained in:
@@ -1,56 +0,0 @@
|
||||
/*##############################################################################
|
||||
## Author: Shaun Reed ##
|
||||
## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ##
|
||||
## About: Classes for managing objects and data within a scene ##
|
||||
## ##
|
||||
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
|
||||
##############################################################################*/
|
||||
|
||||
#ifndef QTK_SCENE_H
|
||||
#define QTK_SCENE_H
|
||||
|
||||
#include <camera3d.h>
|
||||
#include <meshrenderer.h>
|
||||
#include <model.h>
|
||||
#include <skybox.h>
|
||||
|
||||
#include <QMatrix4x4>
|
||||
|
||||
namespace Qtk {
|
||||
class Scene : protected QOpenGLFunctions {
|
||||
friend class MainWidget;
|
||||
|
||||
public:
|
||||
Scene();
|
||||
~Scene();
|
||||
|
||||
virtual void init() = 0;
|
||||
|
||||
virtual void draw() { privDraw(); };
|
||||
virtual void update() = 0;
|
||||
|
||||
static Camera3D & Camera() { return mCamera; }
|
||||
|
||||
static QMatrix4x4 View() { return mCamera.toMatrix(); }
|
||||
|
||||
static QMatrix4x4 & Projection() { return mProjection; }
|
||||
|
||||
inline Skybox * getSkybox() { return mSkybox; }
|
||||
|
||||
inline void setSkybox(Skybox * skybox) { mSkybox = skybox; }
|
||||
|
||||
private:
|
||||
static Camera3D mCamera;
|
||||
static QMatrix4x4 mProjection;
|
||||
bool mInit = false;
|
||||
|
||||
void privDraw();
|
||||
|
||||
protected:
|
||||
Skybox * mSkybox {};
|
||||
std::vector<MeshRenderer *> mMeshes {};
|
||||
std::vector<Model *> mModels {};
|
||||
};
|
||||
} // namespace Qtk
|
||||
|
||||
#endif // QTK_SCENE_H
|
||||
@@ -32,22 +32,22 @@ const QMatrix4x4 & Camera3D::toMatrix() {
|
||||
******************************************************************************/
|
||||
|
||||
QDataStream & operator<<(QDataStream & out, Camera3D & transform) {
|
||||
out << transform.transform();
|
||||
out << transform.getTransform();
|
||||
return out;
|
||||
}
|
||||
|
||||
QDataStream & operator>>(QDataStream & in, Camera3D & transform) {
|
||||
in >> transform.transform();
|
||||
in >> transform.getTransform();
|
||||
return in;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug dbg, const Camera3D & transform) {
|
||||
dbg << "Camera3D\n{\n";
|
||||
dbg << "Position: <" << transform.translation().x() << ", "
|
||||
<< transform.translation().y() << ", " << transform.translation().z()
|
||||
<< ">\n";
|
||||
dbg << "Rotation: <" << transform.rotation().x() << ", "
|
||||
<< transform.rotation().y() << ", " << transform.rotation().z() << " | "
|
||||
<< transform.rotation().scalar() << ">\n}";
|
||||
dbg << "Position: <" << transform.getTranslation().x() << ", "
|
||||
<< transform.getTranslation().y() << ", "
|
||||
<< transform.getTranslation().z() << ">\n";
|
||||
dbg << "Rotation: <" << transform.getRotation().x() << ", "
|
||||
<< transform.getRotation().y() << ", " << transform.getRotation().z()
|
||||
<< " | " << transform.getRotation().scalar() << ">\n}";
|
||||
return dbg;
|
||||
}
|
||||
|
||||
@@ -17,19 +17,25 @@
|
||||
namespace Qtk {
|
||||
class QTKAPI Camera3D {
|
||||
public:
|
||||
// Constants
|
||||
/*************************************************************************
|
||||
* Constants
|
||||
************************************************************************/
|
||||
|
||||
static const QVector3D LocalForward;
|
||||
static const QVector3D LocalUp;
|
||||
static const QVector3D LocalRight;
|
||||
|
||||
// Accessors
|
||||
inline Transform3D & transform() { return mTransform; }
|
||||
/*************************************************************************
|
||||
* Accessors
|
||||
************************************************************************/
|
||||
|
||||
[[nodiscard]] inline const QVector3D & translation() const {
|
||||
inline Transform3D & getTransform() { return mTransform; }
|
||||
|
||||
[[nodiscard]] inline const QVector3D & getTranslation() const {
|
||||
return mTransform.getTranslation();
|
||||
}
|
||||
|
||||
[[nodiscard]] inline const QQuaternion & rotation() const {
|
||||
[[nodiscard]] inline const QQuaternion & getRotation() const {
|
||||
return mTransform.getRotation();
|
||||
}
|
||||
|
||||
@@ -49,9 +55,17 @@ namespace Qtk {
|
||||
}
|
||||
|
||||
private:
|
||||
/*************************************************************************
|
||||
* Private Members
|
||||
************************************************************************/
|
||||
|
||||
Transform3D mTransform;
|
||||
QMatrix4x4 mWorld;
|
||||
|
||||
/*************************************************************************
|
||||
* Private Methods
|
||||
************************************************************************/
|
||||
|
||||
#ifndef QT_NO_DATASTREAM
|
||||
friend QDataStream & operator<<(QDataStream & out, Camera3D & transform);
|
||||
friend QDataStream & operator>>(QDataStream & in, Camera3D & transform);
|
||||
|
||||
17
src/input.h
17
src/input.h
@@ -17,10 +17,15 @@
|
||||
|
||||
namespace Qtk {
|
||||
class QTKAPI Input {
|
||||
public:
|
||||
/*************************************************************************
|
||||
* Typedefs
|
||||
************************************************************************/
|
||||
friend class Qtk::QtkWidget;
|
||||
|
||||
public:
|
||||
// Possible key states
|
||||
/**
|
||||
* Possible key states
|
||||
*/
|
||||
enum InputState {
|
||||
InputInvalid,
|
||||
InputRegistered,
|
||||
@@ -30,6 +35,10 @@ namespace Qtk {
|
||||
InputReleased
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* Public Methods
|
||||
************************************************************************/
|
||||
|
||||
// State checking
|
||||
inline static bool keyTriggered(Qt::Key key) {
|
||||
return keyState(key) == InputTriggered;
|
||||
@@ -63,6 +72,10 @@ namespace Qtk {
|
||||
static QPoint mouseDelta();
|
||||
|
||||
private:
|
||||
/*************************************************************************
|
||||
* Private Methods
|
||||
************************************************************************/
|
||||
|
||||
// State updating
|
||||
static void update();
|
||||
static void registerKeyPress(int key);
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/*##############################################################################
|
||||
## Author: Shaun Reed ##
|
||||
## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ##
|
||||
## About: Main window for Qt6 OpenGL widget application ##
|
||||
## ##
|
||||
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
|
||||
##############################################################################*/
|
||||
#ifndef QTK_MAINWIDGET_H
|
||||
#define QTK_MAINWIDGET_H
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <QMatrix4x4>
|
||||
#include <QOpenGLDebugLogger>
|
||||
#include <QOpenGLFunctions>
|
||||
#include <QOpenGLWidget>
|
||||
|
||||
#define QTK_DEBUG
|
||||
|
||||
class MeshRenderer;
|
||||
|
||||
class Model;
|
||||
|
||||
class Object;
|
||||
|
||||
class Scene;
|
||||
|
||||
class Skybox;
|
||||
|
||||
class OpenGLTextureFactory;
|
||||
|
||||
class MainWidget : public QOpenGLWidget, protected QOpenGLFunctions {
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
// Constructors
|
||||
MainWidget();
|
||||
explicit MainWidget(QWidget * parent);
|
||||
explicit MainWidget(const QSurfaceFormat & format);
|
||||
~MainWidget() override;
|
||||
|
||||
private:
|
||||
void teardownGL();
|
||||
void initObjects();
|
||||
|
||||
public:
|
||||
// Inherited virtual Members
|
||||
void paintGL() override;
|
||||
void initializeGL() override;
|
||||
void resizeGL(int width, int height) override;
|
||||
|
||||
protected slots:
|
||||
void update();
|
||||
void messageLogged(const QOpenGLDebugMessage & msg);
|
||||
|
||||
// Protected Helpers
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent * event) override;
|
||||
void keyReleaseEvent(QKeyEvent * event) override;
|
||||
void mousePressEvent(QMouseEvent * event) override;
|
||||
void mouseReleaseEvent(QMouseEvent * event) override;
|
||||
|
||||
private:
|
||||
// Private helpers
|
||||
void initializeWidget();
|
||||
void printContextInformation();
|
||||
void updateCameraInput();
|
||||
|
||||
Scene * mScene;
|
||||
Object * mObject;
|
||||
|
||||
QOpenGLDebugLogger * mDebugLogger;
|
||||
};
|
||||
|
||||
#endif // QTK_MAINWIDGET_H
|
||||
354
src/mesh.cpp
354
src/mesh.cpp
@@ -13,6 +13,9 @@ using namespace Qtk;
|
||||
Cube::Cube(DrawMode mode) {
|
||||
mDrawMode = mode;
|
||||
switch(mode) {
|
||||
// The order of the following assignment values helps to visualize.
|
||||
// clang-format off
|
||||
|
||||
// Cube data for use with glDrawArrays
|
||||
case QTK_DRAW_ARRAYS:
|
||||
mIndices = {/* No indices needed for glDrawArrays */};
|
||||
@@ -20,51 +23,76 @@ Cube::Cube(DrawMode mode) {
|
||||
mNormals = {FACE_FRONT, FACE_BACK, FACE_TOP,
|
||||
FACE_BOTTOM, FACE_LEFT, FACE_RIGHT};
|
||||
|
||||
mVertices = {// Face 1 (Front)
|
||||
VERTEX_FTR, VERTEX_FTL, VERTEX_FBL, VERTEX_FBL, VERTEX_FBR,
|
||||
VERTEX_FTR,
|
||||
// Face 2 (Back)
|
||||
VERTEX_BBR, VERTEX_BTL, VERTEX_BTR, VERTEX_BTL, VERTEX_BBR,
|
||||
VERTEX_BBL,
|
||||
// Face 3 (Top)
|
||||
VERTEX_FTR, VERTEX_BTR, VERTEX_BTL, VERTEX_BTL, VERTEX_FTL,
|
||||
VERTEX_FTR,
|
||||
// Face 4 (Bottom)
|
||||
VERTEX_FBR, VERTEX_FBL, VERTEX_BBL, VERTEX_BBL, VERTEX_BBR,
|
||||
VERTEX_FBR,
|
||||
// Face 5 (Left)
|
||||
VERTEX_FBL, VERTEX_FTL, VERTEX_BTL, VERTEX_FBL, VERTEX_BTL,
|
||||
VERTEX_BBL,
|
||||
// Face 6 (Right)
|
||||
VERTEX_FTR, VERTEX_FBR, VERTEX_BBR, VERTEX_BBR, VERTEX_BTR,
|
||||
VERTEX_FTR};
|
||||
// We're drawing triangles to construct the geometry of a cube.
|
||||
// Each triangle is made up of three points.
|
||||
// The entire cube has 12 triangles to make 6 square faces of the cube.
|
||||
mVertices = {
|
||||
// Face 1 (Front)
|
||||
VERTEX_FTR, VERTEX_FTL, VERTEX_FBL,
|
||||
VERTEX_FBL, VERTEX_FBR, VERTEX_FTR,
|
||||
// Face 2 (Back)
|
||||
VERTEX_BBR, VERTEX_BTL, VERTEX_BTR,
|
||||
VERTEX_BTL, VERTEX_BBR, VERTEX_BBL,
|
||||
// Face 3 (Top)
|
||||
VERTEX_FTR, VERTEX_BTR, VERTEX_BTL,
|
||||
VERTEX_BTL, VERTEX_FTL, VERTEX_FTR,
|
||||
// Face 4 (Bottom)
|
||||
VERTEX_FBR, VERTEX_FBL, VERTEX_BBL,
|
||||
VERTEX_BBL, VERTEX_BBR, VERTEX_FBR,
|
||||
// Face 5 (Left)
|
||||
VERTEX_FBL, VERTEX_FTL, VERTEX_BTL,
|
||||
VERTEX_FBL, VERTEX_BTL, VERTEX_BBL,
|
||||
// Face 6 (Right)
|
||||
VERTEX_FTR, VERTEX_FBR, VERTEX_BBR,
|
||||
VERTEX_BBR, VERTEX_BTR, VERTEX_FTR
|
||||
};
|
||||
|
||||
mColors = {// Face 1 (Front)
|
||||
RED, GREEN, BLUE, BLUE, WHITE, RED,
|
||||
// Face 2 (Back)
|
||||
YELLOW, CYAN, MAGENTA, CYAN, YELLOW, BLACK,
|
||||
// Face 3 (Top)
|
||||
RED, MAGENTA, CYAN, CYAN, GREEN, RED,
|
||||
// Face 4 (Bottom)
|
||||
WHITE, BLUE, BLACK, BLACK, YELLOW, WHITE,
|
||||
// Face 5 (Left)
|
||||
BLUE, GREEN, CYAN, BLUE, CYAN, BLACK,
|
||||
// Face 6 (Right)
|
||||
RED, WHITE, YELLOW, YELLOW, MAGENTA, RED};
|
||||
// Setting colors for each vertex that we defined above.
|
||||
// These are defaults and can be overriden by the caller with setColor().
|
||||
// The colors below are interpolated from vertex to vertex.
|
||||
mColors = {
|
||||
// Face 1 (Front)
|
||||
RED, GREEN, BLUE,
|
||||
BLUE, WHITE, RED,
|
||||
// Face 2 (Back)
|
||||
YELLOW, CYAN, MAGENTA,
|
||||
CYAN, YELLOW, BLACK,
|
||||
// Face 3 (Top)
|
||||
RED, MAGENTA, CYAN,
|
||||
CYAN, GREEN, RED,
|
||||
// Face 4 (Bottom)
|
||||
WHITE, BLUE, BLACK,
|
||||
BLACK, YELLOW, WHITE,
|
||||
// Face 5 (Left)
|
||||
BLUE, GREEN, CYAN,
|
||||
BLUE, CYAN, BLACK,
|
||||
// Face 6 (Right)
|
||||
RED, WHITE, YELLOW,
|
||||
YELLOW, MAGENTA, RED
|
||||
};
|
||||
|
||||
mTexCoords = {// Face 1 (Front)
|
||||
UV_TOP, UV_ORIGIN, UV_RIGHT, UV_RIGHT, UV_CORNER, UV_TOP,
|
||||
// Face 2 (Back)
|
||||
UV_TOP, UV_RIGHT, UV_CORNER, UV_RIGHT, UV_TOP, UV_ORIGIN,
|
||||
// Face 3 (Top)
|
||||
UV_CORNER, UV_TOP, UV_ORIGIN, UV_ORIGIN, UV_RIGHT,
|
||||
UV_CORNER,
|
||||
// Face 4 (Bottom)
|
||||
UV_TOP, UV_ORIGIN, UV_RIGHT, UV_RIGHT, UV_CORNER, UV_TOP,
|
||||
// Face 5 (Left)
|
||||
UV_TOP, UV_CORNER, UV_RIGHT, UV_TOP, UV_RIGHT, UV_ORIGIN,
|
||||
// Face 6 (Right)
|
||||
UV_TOP, UV_CORNER, UV_RIGHT, UV_RIGHT, UV_ORIGIN, UV_TOP};
|
||||
// Define texture coordinates for the cube.
|
||||
// This defines the orientation of the texture when applied the object.
|
||||
mTexCoords = {
|
||||
// Face 1 (Front)
|
||||
UV_TOP, UV_ORIGIN, UV_RIGHT,
|
||||
UV_RIGHT, UV_CORNER, UV_TOP,
|
||||
// Face 2 (Back)
|
||||
UV_TOP, UV_RIGHT, UV_CORNER,
|
||||
UV_RIGHT, UV_TOP, UV_ORIGIN,
|
||||
// Face 3 (Top)
|
||||
UV_CORNER, UV_TOP, UV_ORIGIN,
|
||||
UV_ORIGIN, UV_RIGHT, UV_CORNER,
|
||||
// Face 4 (Bottom)
|
||||
UV_TOP, UV_ORIGIN, UV_RIGHT,
|
||||
UV_RIGHT, UV_CORNER, UV_TOP,
|
||||
// Face 5 (Left)
|
||||
UV_TOP, UV_CORNER, UV_RIGHT,
|
||||
UV_TOP, UV_RIGHT, UV_ORIGIN,
|
||||
// Face 6 (Right)
|
||||
UV_TOP, UV_CORNER, UV_RIGHT,
|
||||
UV_RIGHT, UV_ORIGIN, UV_TOP
|
||||
};
|
||||
|
||||
break;
|
||||
|
||||
@@ -81,56 +109,64 @@ Cube::Cube(DrawMode mode) {
|
||||
VERTEX_FTR, VERTEX_FTL, VERTEX_FBL, VERTEX_FBR,
|
||||
// 4 5 6 7
|
||||
VERTEX_BTR, VERTEX_BTL, VERTEX_BBL, VERTEX_BBR};
|
||||
mIndices = {// Face 1 (Front)
|
||||
0, 1, 2, 2, 3, 0,
|
||||
// Face 2 (Back)
|
||||
7, 5, 4, 5, 7, 6,
|
||||
// Face 3 (Top)
|
||||
0, 4, 5, 5, 1, 0,
|
||||
// Face 4 (Bottom)
|
||||
3, 2, 6, 6, 7, 3,
|
||||
// Face 5 (Left)
|
||||
2, 1, 5, 2, 5, 6,
|
||||
// Face 6 (Right)
|
||||
0, 3, 7, 7, 4, 0};
|
||||
|
||||
mIndices = {
|
||||
// Face 1 (Front)
|
||||
0, 1, 2, 2, 3, 0,
|
||||
// Face 2 (Back)
|
||||
7, 5, 4, 5, 7, 6,
|
||||
// Face 3 (Top)
|
||||
0, 4, 5, 5, 1, 0,
|
||||
// Face 4 (Bottom)
|
||||
3, 2, 6, 6, 7, 3,
|
||||
// Face 5 (Left)
|
||||
2, 1, 5, 2, 5, 6,
|
||||
// Face 6 (Right)
|
||||
0, 3, 7, 7, 4, 0
|
||||
};
|
||||
|
||||
break;
|
||||
|
||||
// Cube shape data for using normals and UVs with glDrawElements
|
||||
case QTK_DRAW_ELEMENTS_NORMALS:
|
||||
mColors = {RED, GREEN, BLUE, WHITE, YELLOW, CYAN, MAGENTA, BLACK};
|
||||
|
||||
mVertices = {// Face 1 (Front)
|
||||
// 0 1 2 3
|
||||
VERTEX_FTL, VERTEX_FBL, VERTEX_FBR, VERTEX_FTR,
|
||||
// Face 2 (Back)
|
||||
// 4 5 6 7
|
||||
VERTEX_BTL, VERTEX_BBL, VERTEX_BBR, VERTEX_BTR,
|
||||
// Face 3 (Top)
|
||||
// 8 9 10 11
|
||||
VERTEX_FTL, VERTEX_BTL, VERTEX_BTR, VERTEX_FTR,
|
||||
// Face 4 (Bottom)
|
||||
// 12 13 14 15
|
||||
VERTEX_FBL, VERTEX_BBL, VERTEX_BBR, VERTEX_FBR,
|
||||
// Face 5 (Left)
|
||||
// 16 17 18 19
|
||||
VERTEX_FBL, VERTEX_BBL, VERTEX_BTL, VERTEX_FTL,
|
||||
// Face 6 (Right)
|
||||
// 20 21 22 23
|
||||
VERTEX_FBR, VERTEX_BBR, VERTEX_BTR, VERTEX_FTR};
|
||||
mVertices = {
|
||||
// Face 1 (Front)
|
||||
// 0 1 2 3
|
||||
VERTEX_FTL, VERTEX_FBL, VERTEX_FBR, VERTEX_FTR,
|
||||
// Face 2 (Back)
|
||||
// 4 5 6 7
|
||||
VERTEX_BTL, VERTEX_BBL, VERTEX_BBR, VERTEX_BTR,
|
||||
// Face 3 (Top)
|
||||
// 8 9 10 11
|
||||
VERTEX_FTL, VERTEX_BTL, VERTEX_BTR, VERTEX_FTR,
|
||||
// Face 4 (Bottom)
|
||||
// 12 13 14 15
|
||||
VERTEX_FBL, VERTEX_BBL, VERTEX_BBR, VERTEX_FBR,
|
||||
// Face 5 (Left)
|
||||
// 16 17 18 19
|
||||
VERTEX_FBL, VERTEX_BBL, VERTEX_BTL, VERTEX_FTL,
|
||||
// Face 6 (Right)
|
||||
// 20 21 22 23
|
||||
VERTEX_FBR, VERTEX_BBR, VERTEX_BTR, VERTEX_FTR
|
||||
};
|
||||
|
||||
mIndices = {// Face 1 (Front)
|
||||
0, 1, 2, 2, 3, 0,
|
||||
// Face 2 (Back)
|
||||
4, 5, 6, 6, 7, 4,
|
||||
// Face 3 (Top)
|
||||
8, 9, 10, 10, 11, 8,
|
||||
// Face 4 (Bottom)
|
||||
12, 13, 14, 14, 15, 12,
|
||||
mIndices = {
|
||||
// Face 1 (Front)
|
||||
0, 1, 2, 2, 3, 0,
|
||||
// Face 2 (Back)
|
||||
4, 5, 6, 6, 7, 4,
|
||||
// Face 3 (Top)
|
||||
8, 9, 10, 10, 11, 8,
|
||||
// Face 4 (Bottom)
|
||||
12, 13, 14, 14, 15, 12,
|
||||
// Face 5 (Left)
|
||||
16, 17, 18, 18, 19, 16,
|
||||
// Face 6 (Right)
|
||||
20, 21, 22, 22, 23, 20
|
||||
};
|
||||
|
||||
// Face 5 (Left)
|
||||
16, 17, 18, 18, 19, 16,
|
||||
// Face 6 (Right)
|
||||
20, 21, 22, 22, 23, 20};
|
||||
|
||||
mNormals = {
|
||||
VECTOR_FORWARD, VECTOR_FORWARD, VECTOR_FORWARD, VECTOR_FORWARD,
|
||||
@@ -143,50 +179,27 @@ Cube::Cube(DrawMode mode) {
|
||||
|
||||
mTexCoords = {
|
||||
// Face 1 (Front)
|
||||
UV_TOP,
|
||||
UV_RIGHT,
|
||||
UV_CORNER,
|
||||
UV_RIGHT,
|
||||
UV_TOP,
|
||||
UV_ORIGIN,
|
||||
UV_TOP, UV_RIGHT, UV_CORNER,
|
||||
UV_RIGHT, UV_TOP, UV_ORIGIN,
|
||||
// Face 2 (Back)
|
||||
UV_TOP,
|
||||
UV_RIGHT,
|
||||
UV_CORNER,
|
||||
UV_RIGHT,
|
||||
UV_TOP,
|
||||
UV_ORIGIN,
|
||||
UV_TOP, UV_RIGHT, UV_CORNER,
|
||||
UV_RIGHT, UV_TOP, UV_ORIGIN,
|
||||
// Face 3 (Top)
|
||||
UV_TOP,
|
||||
UV_RIGHT,
|
||||
UV_CORNER,
|
||||
UV_RIGHT,
|
||||
UV_TOP,
|
||||
UV_ORIGIN,
|
||||
UV_TOP, UV_RIGHT, UV_CORNER,
|
||||
UV_RIGHT, UV_TOP, UV_ORIGIN,
|
||||
// Face 4 (Bottom)
|
||||
UV_TOP,
|
||||
UV_RIGHT,
|
||||
UV_CORNER,
|
||||
UV_RIGHT,
|
||||
UV_TOP,
|
||||
UV_ORIGIN,
|
||||
UV_TOP, UV_RIGHT, UV_CORNER,
|
||||
UV_RIGHT, UV_TOP, UV_ORIGIN,
|
||||
// Face 5 (Left)
|
||||
UV_TOP,
|
||||
UV_RIGHT,
|
||||
UV_CORNER,
|
||||
UV_RIGHT,
|
||||
UV_TOP,
|
||||
UV_ORIGIN,
|
||||
UV_TOP, UV_RIGHT, UV_CORNER,
|
||||
UV_RIGHT, UV_TOP, UV_ORIGIN,
|
||||
// Face 6 (Right)
|
||||
UV_TOP,
|
||||
UV_RIGHT,
|
||||
UV_CORNER,
|
||||
UV_RIGHT,
|
||||
UV_TOP,
|
||||
UV_ORIGIN,
|
||||
UV_TOP, UV_RIGHT, UV_CORNER,
|
||||
UV_RIGHT, UV_TOP, UV_ORIGIN,
|
||||
};
|
||||
|
||||
break;
|
||||
// clang-format on
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,6 +207,8 @@ Triangle::Triangle(DrawMode mode) {
|
||||
mDrawMode = mode;
|
||||
const QVector3D triangleTop = QVector3D(0.0f, 0.5f, 0.0f);
|
||||
switch(mode) {
|
||||
// clang-format off
|
||||
|
||||
case QTK_DRAW_ARRAYS:
|
||||
mIndices = {/* No indices needed for glDrawArrays */};
|
||||
|
||||
@@ -201,29 +216,17 @@ Triangle::Triangle(DrawMode mode) {
|
||||
|
||||
mVertices = {
|
||||
// Bottom face (Base of the pyramid)
|
||||
VERTEX_BBL,
|
||||
VERTEX_BBR,
|
||||
VERTEX_FBR,
|
||||
VERTEX_FBR,
|
||||
VERTEX_FBL,
|
||||
VERTEX_BBL,
|
||||
VERTEX_BBL, VERTEX_BBR, VERTEX_FBR,
|
||||
VERTEX_FBR, VERTEX_FBL, VERTEX_BBL,
|
||||
|
||||
// Front face
|
||||
VERTEX_FBL,
|
||||
VERTEX_FBR,
|
||||
triangleTop,
|
||||
VERTEX_FBL, VERTEX_FBR, triangleTop,
|
||||
// Back face
|
||||
VERTEX_BBR,
|
||||
VERTEX_BBL,
|
||||
triangleTop,
|
||||
VERTEX_BBR, VERTEX_BBL, triangleTop,
|
||||
// Left face
|
||||
VERTEX_BBL,
|
||||
VERTEX_FBL,
|
||||
triangleTop,
|
||||
VERTEX_BBL, VERTEX_FBL, triangleTop,
|
||||
// Right face
|
||||
VERTEX_FBR,
|
||||
VERTEX_BBR,
|
||||
triangleTop,
|
||||
VERTEX_FBR, VERTEX_BBR, triangleTop,
|
||||
};
|
||||
|
||||
// Find normals for each triangle of the mesh
|
||||
@@ -238,29 +241,17 @@ Triangle::Triangle(DrawMode mode) {
|
||||
|
||||
mTexCoords = {
|
||||
// Bottom face (Base of the pyramid)
|
||||
UV_ORIGIN,
|
||||
UV_RIGHT,
|
||||
UV_CORNER,
|
||||
UV_CORNER,
|
||||
UV_TOP,
|
||||
UV_ORIGIN,
|
||||
UV_ORIGIN, UV_RIGHT, UV_CORNER,
|
||||
UV_CORNER, UV_TOP, UV_ORIGIN,
|
||||
|
||||
// Front face
|
||||
UV_ORIGIN,
|
||||
UV_RIGHT,
|
||||
UV_CORNER,
|
||||
UV_ORIGIN, UV_RIGHT, UV_CORNER,
|
||||
// Back face
|
||||
UV_ORIGIN,
|
||||
UV_RIGHT,
|
||||
UV_CORNER,
|
||||
UV_ORIGIN, UV_RIGHT, UV_CORNER,
|
||||
// Left face
|
||||
UV_ORIGIN,
|
||||
UV_RIGHT,
|
||||
UV_CORNER,
|
||||
UV_ORIGIN, UV_RIGHT, UV_CORNER,
|
||||
// Right face
|
||||
UV_ORIGIN,
|
||||
UV_RIGHT,
|
||||
UV_CORNER,
|
||||
UV_ORIGIN, UV_RIGHT, UV_CORNER,
|
||||
};
|
||||
|
||||
break;
|
||||
@@ -296,34 +287,22 @@ Triangle::Triangle(DrawMode mode) {
|
||||
mVertices = {
|
||||
// Bottom face
|
||||
// 0 1 2
|
||||
VERTEX_FBL,
|
||||
VERTEX_FBR,
|
||||
VERTEX_BBL,
|
||||
VERTEX_FBL, VERTEX_FBR, VERTEX_BBL,
|
||||
// 3 4 5
|
||||
VERTEX_BBR,
|
||||
VERTEX_FBR,
|
||||
VERTEX_BBL,
|
||||
VERTEX_BBR, VERTEX_FBR, VERTEX_BBL,
|
||||
|
||||
// Front face
|
||||
// 6 7 8
|
||||
VERTEX_FBL,
|
||||
VERTEX_FBR,
|
||||
triangleTop,
|
||||
VERTEX_FBL, VERTEX_FBR, triangleTop,
|
||||
// Back face
|
||||
// 9 10 11
|
||||
VERTEX_BBR,
|
||||
VERTEX_BBL,
|
||||
triangleTop,
|
||||
VERTEX_BBR, VERTEX_BBL, triangleTop,
|
||||
// Left face
|
||||
// 12 13 14
|
||||
VERTEX_BBL,
|
||||
VERTEX_FBL,
|
||||
triangleTop,
|
||||
VERTEX_BBL, VERTEX_FBL, triangleTop,
|
||||
// Right face
|
||||
// 15 16 17
|
||||
VERTEX_FBR,
|
||||
VERTEX_BBR,
|
||||
triangleTop,
|
||||
VERTEX_FBR, VERTEX_BBR, triangleTop,
|
||||
};
|
||||
|
||||
mIndices = {
|
||||
@@ -350,30 +329,19 @@ Triangle::Triangle(DrawMode mode) {
|
||||
|
||||
mTexCoords = {
|
||||
// Bottom face
|
||||
UV_ORIGIN,
|
||||
UV_RIGHT,
|
||||
UV_TOP,
|
||||
UV_CORNER,
|
||||
UV_RIGHT,
|
||||
UV_TOP,
|
||||
UV_ORIGIN, UV_RIGHT, UV_TOP,
|
||||
UV_CORNER, UV_RIGHT, UV_TOP,
|
||||
|
||||
// Front face
|
||||
UV_ORIGIN,
|
||||
UV_RIGHT,
|
||||
UV_CORNER,
|
||||
UV_ORIGIN, UV_RIGHT, UV_CORNER,
|
||||
// Back face
|
||||
UV_ORIGIN,
|
||||
UV_RIGHT,
|
||||
UV_CORNER,
|
||||
UV_ORIGIN, UV_RIGHT, UV_CORNER,
|
||||
// Left face
|
||||
UV_ORIGIN,
|
||||
UV_RIGHT,
|
||||
UV_CORNER,
|
||||
UV_ORIGIN, UV_RIGHT, UV_CORNER,
|
||||
// Right face
|
||||
UV_ORIGIN,
|
||||
UV_RIGHT,
|
||||
UV_CORNER,
|
||||
UV_ORIGIN, UV_RIGHT, UV_CORNER,
|
||||
};
|
||||
break;
|
||||
// clang-format on
|
||||
}
|
||||
}
|
||||
|
||||
67
src/mesh.h
67
src/mesh.h
@@ -46,21 +46,22 @@ namespace Qtk {
|
||||
#define VECTOR_ONE QVector3D(1.0f, 1.0f, 1.0f)
|
||||
#define VECTOR_ZERO QVector3D(0.0f, 0.0f, 0.0f)
|
||||
|
||||
// clang-format off
|
||||
// A series of direction vectors to represent cube face normal
|
||||
#define FACE_TOP \
|
||||
VECTOR_UP, VECTOR_UP, VECTOR_UP, VECTOR_UP, VECTOR_UP, VECTOR_UP
|
||||
#define FACE_BOTTOM \
|
||||
VECTOR_DOWN, VECTOR_DOWN, VECTOR_DOWN, VECTOR_DOWN, VECTOR_DOWN, VECTOR_DOWN
|
||||
#define FACE_LEFT \
|
||||
VECTOR_LEFT, VECTOR_LEFT, VECTOR_LEFT, VECTOR_LEFT, VECTOR_LEFT, VECTOR_LEFT
|
||||
#define FACE_RIGHT \
|
||||
VECTOR_RIGHT, VECTOR_RIGHT, VECTOR_RIGHT, VECTOR_RIGHT, VECTOR_RIGHT, \
|
||||
VECTOR_RIGHT
|
||||
#define FACE_FRONT \
|
||||
VECTOR_FORWARD, VECTOR_FORWARD, VECTOR_FORWARD, VECTOR_FORWARD, \
|
||||
VECTOR_FORWARD, VECTOR_FORWARD
|
||||
#define FACE_BACK \
|
||||
VECTOR_BACK, VECTOR_BACK, VECTOR_BACK, VECTOR_BACK, VECTOR_BACK, VECTOR_BACK
|
||||
#define FACE_TOP VECTOR_UP, VECTOR_UP, VECTOR_UP, \
|
||||
VECTOR_UP, VECTOR_UP, VECTOR_UP
|
||||
#define FACE_BOTTOM VECTOR_DOWN, VECTOR_DOWN, VECTOR_DOWN, \
|
||||
VECTOR_DOWN, VECTOR_DOWN, VECTOR_DOWN
|
||||
#define FACE_LEFT VECTOR_LEFT, VECTOR_LEFT, VECTOR_LEFT, \
|
||||
VECTOR_LEFT, VECTOR_LEFT, VECTOR_LEFT
|
||||
#define FACE_RIGHT VECTOR_RIGHT, VECTOR_RIGHT, VECTOR_RIGHT, \
|
||||
VECTOR_RIGHT, VECTOR_RIGHT, VECTOR_RIGHT
|
||||
#define FACE_FRONT VECTOR_FORWARD, VECTOR_FORWARD, VECTOR_FORWARD, \
|
||||
VECTOR_FORWARD, VECTOR_FORWARD, VECTOR_FORWARD
|
||||
#define FACE_BACK VECTOR_BACK, VECTOR_BACK, VECTOR_BACK, \
|
||||
VECTOR_BACK, VECTOR_BACK, VECTOR_BACK
|
||||
// clang-format on
|
||||
|
||||
|
||||
// Colors using QVector3Ds as RGB values
|
||||
#define WHITE VECTOR_ONE
|
||||
@@ -84,13 +85,26 @@ namespace Qtk {
|
||||
typedef std::vector<QVector2D> TexCoords;
|
||||
typedef std::vector<QVector3D> Normals;
|
||||
|
||||
/**
|
||||
* The OpenGL draw mode to initialize QTK shape data for.
|
||||
* Different draw modes require different organization of data.
|
||||
* This enum allows us to predefine simple geometry for different draw modes.
|
||||
*/
|
||||
enum DrawMode {
|
||||
QTK_DRAW_ARRAYS,
|
||||
QTK_DRAW_ELEMENTS,
|
||||
QTK_DRAW_ELEMENTS_NORMALS
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class for all simple shape objects.
|
||||
*/
|
||||
struct QTKAPI ShapeBase {
|
||||
public:
|
||||
/*************************************************************************
|
||||
* Constructors / Destructors
|
||||
************************************************************************/
|
||||
|
||||
explicit ShapeBase(
|
||||
DrawMode mode = QTK_DRAW_ARRAYS, Vertices v = {}, Indices i = {},
|
||||
Colors c = {}, TexCoords t = {}, Normals n = {}) :
|
||||
@@ -99,6 +113,10 @@ namespace Qtk {
|
||||
mIndices(std::move(i)), mTexCoords(std::move(t)),
|
||||
mNormals(std::move(n)) {}
|
||||
|
||||
/*************************************************************************
|
||||
* Accessors
|
||||
************************************************************************/
|
||||
|
||||
[[nodiscard]] inline const Vertices & getVertices() const {
|
||||
return mVertices;
|
||||
}
|
||||
@@ -122,6 +140,10 @@ namespace Qtk {
|
||||
}
|
||||
|
||||
protected:
|
||||
/*************************************************************************
|
||||
* Protected Members
|
||||
************************************************************************/
|
||||
|
||||
DrawMode mDrawMode;
|
||||
|
||||
Vertices mVertices {};
|
||||
@@ -132,13 +154,26 @@ namespace Qtk {
|
||||
};
|
||||
|
||||
struct Shape : public ShapeBase {
|
||||
public:
|
||||
/*************************************************************************
|
||||
* Typedefs
|
||||
************************************************************************/
|
||||
|
||||
friend MeshRenderer;
|
||||
friend Object;
|
||||
|
||||
/*************************************************************************
|
||||
* Constructors / Destructors
|
||||
************************************************************************/
|
||||
|
||||
Shape() = default;
|
||||
|
||||
explicit Shape(const ShapeBase & rhs) : ShapeBase(rhs) {}
|
||||
|
||||
/*************************************************************************
|
||||
* Setters
|
||||
************************************************************************/
|
||||
|
||||
virtual inline void setVertices(const Vertices & value) {
|
||||
mVertices = value;
|
||||
}
|
||||
@@ -160,13 +195,15 @@ namespace Qtk {
|
||||
virtual inline void setShape(const Shape & value) { *this = value; }
|
||||
};
|
||||
|
||||
// Primitives inherit from ShapeBase, does not allow setting of shape values
|
||||
/* Primitives inherit from ShapeBase, doesn't allow setting shape values. */
|
||||
class QTKAPI Mesh {};
|
||||
|
||||
/* Simple Cube shape. */
|
||||
struct QTKAPI Cube : public ShapeBase {
|
||||
explicit Cube(DrawMode mode = QTK_DRAW_ARRAYS);
|
||||
};
|
||||
|
||||
/* Simple Triangle shape. */
|
||||
struct QTKAPI Triangle : public ShapeBase {
|
||||
explicit Triangle(DrawMode mode = QTK_DRAW_ARRAYS);
|
||||
};
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
#include <QImageReader>
|
||||
|
||||
#include <abstractscene.h>
|
||||
#include <meshrenderer.h>
|
||||
#include <scene.h>
|
||||
#include <texture.h>
|
||||
|
||||
using namespace Qtk;
|
||||
@@ -31,6 +31,13 @@ MeshRenderer::~MeshRenderer() {
|
||||
|
||||
// Static member function to retrieve instances of MeshRenderers
|
||||
MeshRenderer * MeshRenderer::getInstance(const QString & name) {
|
||||
if(!sInstances.contains(name)) {
|
||||
#if QTK_DEBUG
|
||||
qDebug() << "Attempt to access MeshRenderer instance that does not exist! ("
|
||||
<< qPrintable(name) << ")\n";
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
return sInstances[name];
|
||||
}
|
||||
|
||||
@@ -126,8 +133,8 @@ void MeshRenderer::setShaders(
|
||||
void MeshRenderer::setUniformMVP(
|
||||
const char * model, const char * view, const char * projection) {
|
||||
ShaderBindScope lock(&mProgram, mBound);
|
||||
mProgram.setUniformValue(projection, Scene::Projection());
|
||||
mProgram.setUniformValue(view, Scene::View());
|
||||
mProgram.setUniformValue(projection, Scene::getProjectionMatrix());
|
||||
mProgram.setUniformValue(view, Scene::getViewMatrix());
|
||||
mProgram.setUniformValue(model, mTransform.toMatrix());
|
||||
}
|
||||
|
||||
@@ -141,6 +148,8 @@ void MeshRenderer::setColor(const QVector3D & color) {
|
||||
mShape.mColors[i] = color;
|
||||
}
|
||||
}
|
||||
// TODO: Factor this out so we don't need to reinitialize
|
||||
init();
|
||||
}
|
||||
|
||||
void MeshRenderer::reallocateTexCoords(const TexCoords & t, unsigned dims) {
|
||||
|
||||
@@ -15,31 +15,19 @@
|
||||
#include <utility>
|
||||
|
||||
namespace Qtk {
|
||||
class QTKAPI ShaderBindScope {
|
||||
public:
|
||||
explicit ShaderBindScope(
|
||||
QOpenGLShaderProgram * program, bool was_locked) :
|
||||
mWasBound(was_locked) {
|
||||
mProgram = program;
|
||||
if(!mWasBound) {
|
||||
mProgram->bind();
|
||||
}
|
||||
}
|
||||
|
||||
~ShaderBindScope() {
|
||||
if(!mWasBound) {
|
||||
mProgram->release();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
QOpenGLShaderProgram * mProgram;
|
||||
bool mWasBound;
|
||||
};
|
||||
|
||||
|
||||
class QTKAPI MeshRenderer : public Object {
|
||||
public:
|
||||
/*************************************************************************
|
||||
* Typedefs
|
||||
************************************************************************/
|
||||
|
||||
/* Static QHash of all mesh objects within the scene. */
|
||||
typedef QHash<QString, MeshRenderer *> MeshManager;
|
||||
|
||||
/*************************************************************************
|
||||
* Constructors / Destructors
|
||||
************************************************************************/
|
||||
|
||||
// Delegate constructors
|
||||
MeshRenderer(
|
||||
const char * name, Vertices vertices, Indices indices,
|
||||
@@ -54,12 +42,28 @@ namespace Qtk {
|
||||
MeshRenderer(const char * name, const ShapeBase & shape);
|
||||
~MeshRenderer() override;
|
||||
|
||||
// Retrieve a mesh by name stored within a static QHash
|
||||
static MeshRenderer * getInstance(const QString & name);
|
||||
/*************************************************************************
|
||||
* Public Methods
|
||||
************************************************************************/
|
||||
|
||||
void init();
|
||||
void draw();
|
||||
|
||||
inline void enableAttributeArray(int location) {
|
||||
ShaderBindScope lock(&mProgram, mBound);
|
||||
mVAO.bind();
|
||||
mProgram.enableAttributeArray(location);
|
||||
mVAO.release();
|
||||
}
|
||||
|
||||
void reallocateTexCoords(const TexCoords & t, unsigned dims = 2);
|
||||
|
||||
void reallocateNormals(const Normals & n, unsigned dims = 3);
|
||||
|
||||
/*************************************************************************
|
||||
* Setters
|
||||
************************************************************************/
|
||||
|
||||
// Draw types like GL_TRIANGLES, GL_POINTS, GL_LINES, etc
|
||||
void setDrawType(int drawType) { mDrawType = drawType; }
|
||||
|
||||
@@ -105,21 +109,24 @@ namespace Qtk {
|
||||
mVAO.release();
|
||||
}
|
||||
|
||||
inline void enableAttributeArray(int location) {
|
||||
ShaderBindScope lock(&mProgram, mBound);
|
||||
mVAO.bind();
|
||||
mProgram.enableAttributeArray(location);
|
||||
mVAO.release();
|
||||
}
|
||||
/*************************************************************************
|
||||
* Accessors
|
||||
************************************************************************/
|
||||
|
||||
void reallocateTexCoords(const TexCoords & t, unsigned dims = 2);
|
||||
/**
|
||||
* Retrieve a mesh by name stored within static QHash private member
|
||||
* @param name The name of the MeshRenderer we want to retrieve.
|
||||
* @return Pointer to the MeshRenderer, or nullptr if not found.
|
||||
*/
|
||||
static MeshRenderer * getInstance(const QString & name);
|
||||
|
||||
void reallocateNormals(const Normals & n, unsigned dims = 3);
|
||||
|
||||
// Static QHash of all mesh objects within the scene
|
||||
typedef QHash<QString, MeshRenderer *> MeshManager;
|
||||
Transform3D & getTransform() { return mTransform; }
|
||||
|
||||
private:
|
||||
/*************************************************************************
|
||||
* Private Members
|
||||
************************************************************************/
|
||||
|
||||
static MeshManager sInstances;
|
||||
|
||||
int mDrawType {};
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
#include <abstractscene.h>
|
||||
#include <model.h>
|
||||
#include <resourcemanager.h>
|
||||
#include <scene.h>
|
||||
#include <texture.h>
|
||||
|
||||
using namespace Qtk;
|
||||
@@ -97,8 +97,8 @@ void ModelMesh::draw(QOpenGLShaderProgram & shader) {
|
||||
|
||||
// Set Model View Projection values
|
||||
shader.setUniformValue("uModel", mTransform.toMatrix());
|
||||
shader.setUniformValue("uView", Scene::View());
|
||||
shader.setUniformValue("uProjection", Scene::Projection());
|
||||
shader.setUniformValue("uView", Scene::getViewMatrix());
|
||||
shader.setUniformValue("uProjection", Scene::getProjectionMatrix());
|
||||
|
||||
GLuint diffuseCount = 1;
|
||||
GLuint specularCount = 1;
|
||||
@@ -180,21 +180,6 @@ void Model::flipTexture(const std::string & fileName, bool flipX, bool flipY) {
|
||||
* Model Private Member Functions
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* Loads a model in .obj, .fbx, .gltf, and other formats
|
||||
* For a full list of formats see assimp documentation:
|
||||
* https://github.com/assimp/assimp/blob/master/doc/Fileformats.md
|
||||
*
|
||||
* Models should not be loaded into Qt resource system
|
||||
* Instead pass an *absolute* path to this function
|
||||
* Relative paths will break if Qtk is executed from different locations
|
||||
*
|
||||
* Models can also be loaded from the `qtk/resource` directory using qrc format
|
||||
* loadModel(":/models/backpack/backpack.obj")
|
||||
* See resourcemanager.h for more information
|
||||
*
|
||||
* @param path Absolute path to a model .obj or other format accepted by assimp
|
||||
*/
|
||||
void Model::loadModel(const std::string & path) {
|
||||
Assimp::Importer import;
|
||||
|
||||
@@ -362,7 +347,7 @@ ModelMesh::Textures Model::loadMaterialTextures(
|
||||
// If the texture has not yet been loaded
|
||||
if(!skip) {
|
||||
ModelTexture texture;
|
||||
texture.mTexture = OpenGLTextureFactory::initTexture2D(
|
||||
texture.mTexture = OpenGLTextureFactory::initTexture(
|
||||
std::string(mDirectory + '/' + fileName.C_Str()).c_str(), false,
|
||||
false);
|
||||
texture.mID = texture.mTexture->textureId();
|
||||
@@ -380,7 +365,7 @@ ModelMesh::Textures Model::loadMaterialTextures(
|
||||
}
|
||||
|
||||
void Model::sortModels() {
|
||||
auto cameraPos = Scene::Camera().transform();
|
||||
auto cameraPos = Scene::getCamera().getTransform();
|
||||
auto cameraDistance = [&cameraPos](const ModelMesh & a, const ModelMesh & b) {
|
||||
// Sort by the first vertex position in the model
|
||||
return (cameraPos.getTranslation().distanceToPoint(
|
||||
|
||||
154
src/model.h
154
src/model.h
@@ -28,14 +28,20 @@
|
||||
#include <transform3D.h>
|
||||
|
||||
namespace Qtk {
|
||||
/**
|
||||
* 3D models will store this data for each vertex in geometry.
|
||||
*/
|
||||
struct QTKAPI ModelVertex {
|
||||
QVector3D mPosition;
|
||||
QVector3D mNormal;
|
||||
QVector2D mTextureCoord;
|
||||
QVector3D mTangent;
|
||||
QVector3D mBitangent;
|
||||
QVector2D mTextureCoord;
|
||||
};
|
||||
|
||||
/**
|
||||
* Struct to store model textures. 3D Models may have multiple.
|
||||
*/
|
||||
struct QTKAPI ModelTexture {
|
||||
GLuint mID {};
|
||||
QOpenGLTexture * mTexture {};
|
||||
@@ -45,14 +51,25 @@ namespace Qtk {
|
||||
|
||||
class Model;
|
||||
|
||||
/**
|
||||
* Mesh class specialized for storing 3D model data.
|
||||
* Eventually this can be consolidated into a more generic class.
|
||||
*/
|
||||
class QTKAPI ModelMesh : protected QOpenGLFunctions {
|
||||
public:
|
||||
/*************************************************************************
|
||||
* Typedefs
|
||||
************************************************************************/
|
||||
|
||||
friend Model;
|
||||
typedef std::vector<ModelVertex> Vertices;
|
||||
typedef std::vector<GLuint> Indices;
|
||||
typedef std::vector<ModelTexture> Textures;
|
||||
|
||||
// Constructors, Destructors
|
||||
/*************************************************************************
|
||||
* Constructors, Destructors
|
||||
************************************************************************/
|
||||
|
||||
ModelMesh(
|
||||
Vertices vertices, Indices indices, Textures textures,
|
||||
const char * vertexShader = ":/model-basic.vert",
|
||||
@@ -68,78 +85,177 @@ namespace Qtk {
|
||||
|
||||
~ModelMesh() = default;
|
||||
|
||||
private:
|
||||
void initMesh(const char * vert, const char * frag);
|
||||
/*************************************************************************
|
||||
* Public Methods
|
||||
************************************************************************/
|
||||
|
||||
// ModelMesh Private Members
|
||||
QOpenGLBuffer *mVBO, *mEBO;
|
||||
QOpenGLVertexArrayObject * mVAO;
|
||||
QOpenGLShaderProgram * mProgram;
|
||||
|
||||
public:
|
||||
inline void draw() { draw(*mProgram); }
|
||||
|
||||
void draw(QOpenGLShaderProgram & shader);
|
||||
|
||||
// ModelMesh Public Members
|
||||
/*************************************************************************
|
||||
* Public Members
|
||||
************************************************************************/
|
||||
|
||||
Vertices mVertices {};
|
||||
Indices mIndices {};
|
||||
Textures mTextures {};
|
||||
Transform3D mTransform;
|
||||
|
||||
private:
|
||||
/*************************************************************************
|
||||
* Private Methods
|
||||
************************************************************************/
|
||||
|
||||
void initMesh(const char * vert, const char * frag);
|
||||
|
||||
/*************************************************************************
|
||||
* Private Members
|
||||
************************************************************************/
|
||||
|
||||
QOpenGLBuffer *mVBO, *mEBO;
|
||||
QOpenGLVertexArrayObject * mVAO;
|
||||
QOpenGLShaderProgram * mProgram;
|
||||
};
|
||||
|
||||
/**
|
||||
* Model object that has a ModelMesh.
|
||||
* Top-level object that represents 3D models stored within a scene.
|
||||
*/
|
||||
class QTKAPI Model : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/*************************************************************************
|
||||
* Typedefs
|
||||
************************************************************************/
|
||||
|
||||
/* ModelManager typedef that will manage global model access. */
|
||||
typedef QHash<QString, Model *> ModelManager;
|
||||
|
||||
/*************************************************************************
|
||||
* Constructors, Destructors
|
||||
************************************************************************/
|
||||
|
||||
// Default model shaders are provided but we can override them in the ctor
|
||||
inline Model(
|
||||
const char * name, const char * path,
|
||||
const char * vertexShader = ":/model-basic.vert",
|
||||
const char * fragmentShader = ":/model-basic.frag") :
|
||||
mName(name),
|
||||
mVertexShader(vertexShader), mFragmentShader(fragmentShader) {
|
||||
mModelPath(path), mVertexShader(vertexShader),
|
||||
mFragmentShader(fragmentShader) {
|
||||
loadModel(path);
|
||||
}
|
||||
|
||||
inline ~Model() override { mManager.remove(mName); }
|
||||
|
||||
/*************************************************************************
|
||||
* Public Methods
|
||||
************************************************************************/
|
||||
|
||||
void draw();
|
||||
void draw(QOpenGLShaderProgram & shader);
|
||||
|
||||
/**
|
||||
* Flip a texture associated with this model
|
||||
*
|
||||
* @param fileName The name of the texture to flip as it is stored on disk
|
||||
* @param flipX Flip the texture along the X axis
|
||||
* @param flipY Flip the texture along the Y axis
|
||||
*/
|
||||
void flipTexture(
|
||||
const std::string & fileName, bool flipX = false, bool flipY = true);
|
||||
|
||||
/*************************************************************************
|
||||
* Setters
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* Sets a uniform value
|
||||
*
|
||||
* @tparam T The type of the value we are settings
|
||||
* @param location The uniform location
|
||||
* @param value The value to assign to the uniform
|
||||
*/
|
||||
template <typename T> void setUniform(const char * location, T value) {
|
||||
for(auto & mesh : mMeshes) {
|
||||
mesh.mProgram->bind();
|
||||
|
||||
mesh.mProgram->setUniformValue(location, value);
|
||||
|
||||
mesh.mProgram->release();
|
||||
}
|
||||
}
|
||||
|
||||
Transform3D mTransform;
|
||||
/*************************************************************************
|
||||
* Accessors
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* Accessor function for retrieving a ModelMesh globally.
|
||||
* The mesh is retrieved from the mManager private member.
|
||||
*
|
||||
* @param name The name of the model to load as it was constructed.
|
||||
* @return Pointer to the model stored within the scene.
|
||||
*/
|
||||
static Model * getInstance(const char * name);
|
||||
|
||||
typedef QHash<QString, Model *> ModelManager;
|
||||
Transform3D & getTransform() { return mTransform; }
|
||||
|
||||
private:
|
||||
static ModelManager mManager;
|
||||
/*************************************************************************
|
||||
* Private Methods
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* Loads a model in .obj, .fbx, .gltf, and other formats.
|
||||
* For a full list of formats see assimp documentation:
|
||||
* https://github.com/assimp/assimp/blob/master/doc/Fileformats.md
|
||||
*
|
||||
* Models should not be loaded into Qt resource system.
|
||||
* Instead pass an *absolute* path to this function.
|
||||
* Relative paths will break if Qtk is executed from different locations.
|
||||
*
|
||||
* Models can also be loaded from the `qtk/resource` directory using qrc
|
||||
* format loadModel(":/models/backpack/backpack.obj").
|
||||
* This does not use Qt resource system, it just provides similar syntax
|
||||
* for accessing files within the same `resources/` directory.
|
||||
*
|
||||
* See resourcemanager.h for more information on how this works.
|
||||
*
|
||||
* @param path Absolute path to a model in .obj or another format accepted
|
||||
* by assimp.
|
||||
*/
|
||||
void loadModel(const std::string & path);
|
||||
|
||||
void processNode(aiNode * node, const aiScene * scene);
|
||||
|
||||
ModelMesh processMesh(aiMesh * mesh, const aiScene * scene);
|
||||
|
||||
ModelMesh::Textures loadMaterialTextures(
|
||||
aiMaterial * mat, aiTextureType type, const std::string & typeName);
|
||||
|
||||
void sortModels();
|
||||
|
||||
// Model Private Members
|
||||
/*************************************************************************
|
||||
* Private Members
|
||||
************************************************************************/
|
||||
|
||||
/* The position of this model in 3D space */
|
||||
Transform3D mTransform;
|
||||
|
||||
/* Static QHash used to store and access models globally. */
|
||||
static ModelManager mManager;
|
||||
|
||||
/* Container to store N loaded textures for this model. */
|
||||
ModelMesh::Textures mTexturesLoaded {};
|
||||
/* Container to store N loaded meshes for this model. */
|
||||
std::vector<ModelMesh> mMeshes {};
|
||||
/* The directory this model and it's textures are stored. */
|
||||
std::string mDirectory {};
|
||||
const char *mVertexShader, *mFragmentShader, *mName;
|
||||
/* File names for shaders and 3D model on disk. */
|
||||
const char *mVertexShader, *mFragmentShader, *mModelPath;
|
||||
/* Name of the model object within the scene. */
|
||||
const char * mName;
|
||||
};
|
||||
} // namespace Qtk
|
||||
|
||||
|
||||
62
src/object.h
62
src/object.h
@@ -18,12 +18,24 @@
|
||||
#include <texture.h>
|
||||
|
||||
namespace Qtk {
|
||||
/**
|
||||
* Object base class for objects that can exist within a scene.
|
||||
* An object could be a Cube, Skybox, 3D Model, or other standalone entities.
|
||||
*/
|
||||
class QTKAPI Object : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/*************************************************************************
|
||||
* Typedefs
|
||||
************************************************************************/
|
||||
|
||||
friend MeshRenderer;
|
||||
|
||||
/*************************************************************************
|
||||
* Constructors / Destructors
|
||||
************************************************************************/
|
||||
|
||||
// Initialize an object with no shape data assigned
|
||||
explicit Object(const char * name) :
|
||||
mName(name), mVBO(QOpenGLBuffer::VertexBuffer), mBound(false) {}
|
||||
@@ -35,19 +47,39 @@ namespace Qtk {
|
||||
|
||||
~Object() override = default;
|
||||
|
||||
inline const Colors & getColors() { return mShape.mColors; }
|
||||
/*************************************************************************
|
||||
* Accessors
|
||||
************************************************************************/
|
||||
|
||||
inline const Indices & getIndexData() { return mShape.mIndices; }
|
||||
[[nodiscard]] inline const Colors & getColors() const {
|
||||
return mShape.mColors;
|
||||
}
|
||||
|
||||
inline const Normals & getNormals() { return mShape.mNormals; }
|
||||
[[nodiscard]] inline const Indices & getIndexData() const {
|
||||
return mShape.mIndices;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline const Normals & getNormals() const {
|
||||
return mShape.mNormals;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline const Shape & getShape() const { return mShape; }
|
||||
|
||||
inline const TexCoords & getTexCoords() { return mShape.mTexCoords; }
|
||||
[[nodiscard]] inline const TexCoords & getTexCoords() const {
|
||||
return mShape.mTexCoords;
|
||||
}
|
||||
|
||||
inline Texture & getTexture() { return mTexture; }
|
||||
[[nodiscard]] inline const Texture & getTexture() const {
|
||||
return mTexture;
|
||||
}
|
||||
|
||||
inline const Vertices & getVertices() { return mShape.mVertices; }
|
||||
[[nodiscard]] inline const Vertices & getVertices() const {
|
||||
return mShape.mVertices;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Setters
|
||||
************************************************************************/
|
||||
|
||||
virtual inline void setColors(const Colors & value) {
|
||||
mShape.mColors = value;
|
||||
@@ -84,6 +116,10 @@ namespace Qtk {
|
||||
mShape.mVertices = value;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Public Methods
|
||||
************************************************************************/
|
||||
|
||||
virtual inline void bindShaders() {
|
||||
mBound = true;
|
||||
mProgram.bind();
|
||||
@@ -94,21 +130,19 @@ namespace Qtk {
|
||||
mProgram.release();
|
||||
}
|
||||
|
||||
private:
|
||||
/*************************************************************************
|
||||
* Private Members
|
||||
************************************************************************/
|
||||
|
||||
QOpenGLShaderProgram mProgram;
|
||||
QOpenGLBuffer mVBO, mNBO;
|
||||
QOpenGLVertexArrayObject mVAO;
|
||||
|
||||
Transform3D mTransform;
|
||||
Shape mShape;
|
||||
Texture mTexture;
|
||||
const char * mName;
|
||||
bool mBound;
|
||||
|
||||
private:
|
||||
virtual inline void setTexture(QOpenGLTexture * value) {
|
||||
mTexture.setTexture(value);
|
||||
}
|
||||
|
||||
QOpenGLShaderProgram mProgram;
|
||||
};
|
||||
} // namespace Qtk
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include <abstractscene.h>
|
||||
#include <input.h>
|
||||
#include <mesh.h>
|
||||
#include <qtkwidget.h>
|
||||
#include <scene.h>
|
||||
|
||||
using namespace Qtk;
|
||||
|
||||
@@ -23,7 +23,6 @@ QtkWidget::QtkWidget() : mScene(Q_NULLPTR), mDebugLogger(Q_NULLPTR) {
|
||||
initializeWidget();
|
||||
}
|
||||
|
||||
// Constructor for using this widget in QtDesigner
|
||||
QtkWidget::QtkWidget(QWidget * parent) :
|
||||
QOpenGLWidget(parent), mScene(Q_NULLPTR), mDebugLogger(Q_NULLPTR) {
|
||||
initializeWidget();
|
||||
@@ -41,27 +40,9 @@ QtkWidget::~QtkWidget() {
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Private Member Functions
|
||||
* Public Inherited Virtual Methods
|
||||
******************************************************************************/
|
||||
|
||||
void QtkWidget::teardownGL() {
|
||||
// Nothing to teardown yet...
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Inherited Virtual Member Functions
|
||||
******************************************************************************/
|
||||
|
||||
void QtkWidget::paintGL() {
|
||||
// Clear buffers
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// Draw the scene first, since it handles drawing our skybox
|
||||
if(mScene != Q_NULLPTR) {
|
||||
mScene->draw();
|
||||
}
|
||||
}
|
||||
|
||||
void QtkWidget::initializeGL() {
|
||||
initializeOpenGLFunctions();
|
||||
// Connect the frameSwapped signal to call the update() function
|
||||
@@ -93,11 +74,19 @@ void QtkWidget::initializeGL() {
|
||||
}
|
||||
|
||||
void QtkWidget::resizeGL(int width, int height) {
|
||||
Scene::Projection().setToIdentity();
|
||||
Scene::Projection().perspective(
|
||||
Scene::getProjectionMatrix().setToIdentity();
|
||||
Scene::getProjectionMatrix().perspective(
|
||||
45.0f, float(width) / float(height), 0.1f, 1000.0f);
|
||||
}
|
||||
|
||||
void QtkWidget::paintGL() {
|
||||
// Clear buffers and draw the scene if it is valid.
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
if(mScene != Q_NULLPTR) {
|
||||
mScene->draw();
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Protected Slots
|
||||
******************************************************************************/
|
||||
@@ -175,7 +164,7 @@ void QtkWidget::messageLogged(const QOpenGLDebugMessage & msg) {
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Protected Helpers
|
||||
* Protected Methods
|
||||
******************************************************************************/
|
||||
|
||||
void QtkWidget::keyPressEvent(QKeyEvent * event) {
|
||||
@@ -204,7 +193,7 @@ void QtkWidget::mouseReleaseEvent(QMouseEvent * event) {
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Private Helpers
|
||||
* Private Methods
|
||||
******************************************************************************/
|
||||
|
||||
void QtkWidget::initializeWidget() {
|
||||
@@ -265,31 +254,31 @@ void QtkWidget::updateCameraInput() {
|
||||
static const float rotSpeed = 0.5f;
|
||||
|
||||
// Handle rotations
|
||||
Scene::Camera().transform().rotate(
|
||||
Scene::getCamera().getTransform().rotate(
|
||||
-rotSpeed * Input::mouseDelta().x(), Camera3D::LocalUp);
|
||||
Scene::Camera().transform().rotate(
|
||||
-rotSpeed * Input::mouseDelta().y(), Scene::Camera().right());
|
||||
Scene::getCamera().getTransform().rotate(
|
||||
-rotSpeed * Input::mouseDelta().y(), Scene::getCamera().right());
|
||||
|
||||
// Handle translations
|
||||
QVector3D translation;
|
||||
if(Input::keyPressed(Qt::Key_W)) {
|
||||
translation += Scene::Camera().forward();
|
||||
translation += Scene::getCamera().forward();
|
||||
}
|
||||
if(Input::keyPressed(Qt::Key_S)) {
|
||||
translation -= Scene::Camera().forward();
|
||||
translation -= Scene::getCamera().forward();
|
||||
}
|
||||
if(Input::keyPressed(Qt::Key_A)) {
|
||||
translation -= Scene::Camera().right();
|
||||
translation -= Scene::getCamera().right();
|
||||
}
|
||||
if(Input::keyPressed(Qt::Key_D)) {
|
||||
translation += Scene::Camera().right();
|
||||
translation += Scene::getCamera().right();
|
||||
}
|
||||
if(Input::keyPressed(Qt::Key_Q)) {
|
||||
translation -= Scene::Camera().up() / 2.0f;
|
||||
translation -= Scene::getCamera().up() / 2.0f;
|
||||
}
|
||||
if(Input::keyPressed(Qt::Key_E)) {
|
||||
translation += Scene::Camera().up() / 2.0f;
|
||||
translation += Scene::getCamera().up() / 2.0f;
|
||||
}
|
||||
Scene::Camera().transform().translate(transSpeed * translation);
|
||||
Scene::getCamera().getTransform().translate(transSpeed * translation);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,60 +15,141 @@
|
||||
#include <QOpenGLFunctions>
|
||||
#include <QOpenGLWidget>
|
||||
|
||||
#include <abstractscene.h>
|
||||
#include <qtkapi.h>
|
||||
#include <scene.h>
|
||||
|
||||
namespace Qtk {
|
||||
/**
|
||||
* QtkWidget class to define required QOpenGLWidget functionality.
|
||||
*
|
||||
* This object has a Scene attached which manages the objects to render.
|
||||
* Client input is passed through this widget to control the camera view.
|
||||
*/
|
||||
class QTKAPI QtkWidget : public QOpenGLWidget, protected QOpenGLFunctions {
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
// Constructors
|
||||
/*************************************************************************
|
||||
* Contructors / Destructors
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* Default ctor will configure a QSurfaceFormat with default settings.
|
||||
*/
|
||||
QtkWidget();
|
||||
|
||||
/**
|
||||
* Qt Designer will call this ctor when creating this widget as a child.
|
||||
*
|
||||
* @param parent The parent QWidget
|
||||
*/
|
||||
explicit QtkWidget(QWidget * parent);
|
||||
|
||||
/**
|
||||
* Allow constructing the widget with a preconfigured QSurfaceFormat.
|
||||
*
|
||||
* @param format QSurfaceFormat already configured by the caller.
|
||||
*/
|
||||
explicit QtkWidget(const QSurfaceFormat & format);
|
||||
|
||||
~QtkWidget() override;
|
||||
|
||||
private:
|
||||
void teardownGL();
|
||||
/*************************************************************************
|
||||
* Private Methods
|
||||
************************************************************************/
|
||||
|
||||
// clang-format off
|
||||
void teardownGL() { /* Nothing to teardown yet... */ }
|
||||
// clang-format on
|
||||
|
||||
public:
|
||||
// Inherited virtual Members
|
||||
void paintGL() override;
|
||||
/*************************************************************************
|
||||
* Public Inherited Virtual Methods
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* Called when the widget is first constructed.
|
||||
*/
|
||||
void initializeGL() override;
|
||||
|
||||
/**
|
||||
* Called when the application window is resized.
|
||||
*
|
||||
* @param width The new width of the window.
|
||||
* @param height The new height of the window.
|
||||
*/
|
||||
void resizeGL(int width, int height) override;
|
||||
|
||||
/**
|
||||
* Called when OpenGL repaints the widget.
|
||||
*/
|
||||
void paintGL() override;
|
||||
|
||||
/*************************************************************************
|
||||
* Accessors
|
||||
************************************************************************/
|
||||
|
||||
inline Qtk::Scene * getScene() { return mScene; }
|
||||
|
||||
/*************************************************************************
|
||||
* Setters
|
||||
************************************************************************/
|
||||
|
||||
inline void setScene(Qtk::Scene * scene) {
|
||||
delete mScene;
|
||||
|
||||
mScene = scene;
|
||||
}
|
||||
|
||||
protected slots:
|
||||
/*************************************************************************
|
||||
* Qt Slots
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* Called when the `frameSwapped` signal is caught.
|
||||
* See definition of initializeGL()
|
||||
*/
|
||||
void update();
|
||||
|
||||
#ifdef QTK_DEBUG
|
||||
/**
|
||||
* Called when the `messageLogged` signal is caught.
|
||||
* See definition of initializeGL()
|
||||
*
|
||||
* @param msg The message logged.
|
||||
*/
|
||||
static void messageLogged(const QOpenGLDebugMessage & msg);
|
||||
#endif
|
||||
|
||||
// Protected Helpers
|
||||
protected:
|
||||
/*************************************************************************
|
||||
* Protected Methods
|
||||
************************************************************************/
|
||||
|
||||
void keyPressEvent(QKeyEvent * event) override;
|
||||
void keyReleaseEvent(QKeyEvent * event) override;
|
||||
void mousePressEvent(QMouseEvent * event) override;
|
||||
void mouseReleaseEvent(QMouseEvent * event) override;
|
||||
|
||||
private:
|
||||
// Private helpers
|
||||
/*************************************************************************
|
||||
* Private Methods
|
||||
************************************************************************/
|
||||
|
||||
void initializeWidget();
|
||||
static void updateCameraInput();
|
||||
|
||||
Qtk::Scene * mScene;
|
||||
#ifdef QTK_DEBUG
|
||||
void printContextInformation();
|
||||
QOpenGLDebugLogger * mDebugLogger;
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
* Private Members
|
||||
************************************************************************/
|
||||
|
||||
Qtk::Scene * mScene;
|
||||
};
|
||||
} // namespace Qtk
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
|
||||
##############################################################################*/
|
||||
|
||||
#include <abstractscene.h>
|
||||
#include <camera3d.h>
|
||||
#include <resourcemanager.h>
|
||||
#include <scene.h>
|
||||
#include <texture.h>
|
||||
|
||||
using namespace Qtk;
|
||||
@@ -21,8 +21,8 @@ QMatrix4x4 Scene::mProjection;
|
||||
******************************************************************************/
|
||||
|
||||
Scene::Scene() {
|
||||
mCamera.transform().setTranslation(0.0f, 0.0f, 20.0f);
|
||||
mCamera.transform().setRotation(-5.0f, 0.0f, 1.0f, 0.0f);
|
||||
mCamera.getTransform().setTranslation(0.0f, 0.0f, 20.0f);
|
||||
mCamera.getTransform().setRotation(-5.0f, 0.0f, 1.0f, 0.0f);
|
||||
}
|
||||
|
||||
Scene::~Scene() {
|
||||
@@ -32,11 +32,10 @@ Scene::~Scene() {
|
||||
for(auto & model : mModels) {
|
||||
delete model;
|
||||
}
|
||||
|
||||
delete mSkybox;
|
||||
}
|
||||
|
||||
void Scene::privDraw() {
|
||||
void Scene::privateDraw() {
|
||||
if(!mInit) {
|
||||
initializeOpenGLFunctions();
|
||||
init();
|
||||
125
src/scene.h
Normal file
125
src/scene.h
Normal file
@@ -0,0 +1,125 @@
|
||||
/*##############################################################################
|
||||
## Author: Shaun Reed ##
|
||||
## Legal: All Content (c) 2022 Shaun Reed, all rights reserved ##
|
||||
## About: Classes for managing objects and data within a scene ##
|
||||
## ##
|
||||
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
|
||||
##############################################################################*/
|
||||
|
||||
#ifndef QTK_SCENE_H
|
||||
#define QTK_SCENE_H
|
||||
|
||||
#include <camera3d.h>
|
||||
#include <meshrenderer.h>
|
||||
#include <model.h>
|
||||
#include <skybox.h>
|
||||
|
||||
#include <QMatrix4x4>
|
||||
|
||||
namespace Qtk {
|
||||
/**
|
||||
* An abstract Scene class to inherit from when building new scenes.
|
||||
*
|
||||
* This class provides the following objects to any inheriting scene:
|
||||
* Skybox, Camera
|
||||
* This class also provides containers for N instances of these objects:
|
||||
* MeshRenderers, Models
|
||||
*
|
||||
* To inherit from this class and define our own scene we must:
|
||||
*
|
||||
* Override and define the `init()` virtual member function. If we want our
|
||||
* scene to render using a Skybox, we should also initialize the mSkybox
|
||||
* member within the overridden definition of `init()` using
|
||||
* `Scene::setSkybox(...)`
|
||||
*
|
||||
* If the scene is to render any kind of movement we are required to override
|
||||
* the `update()` virtual method.
|
||||
*
|
||||
* If the child scene adds any objects which are not managed (drawn) by this
|
||||
* base class, the child scene class must also override the `draw()` method.
|
||||
*/
|
||||
class Scene : protected QOpenGLFunctions {
|
||||
public:
|
||||
/*************************************************************************
|
||||
* Contructors / Destructors
|
||||
************************************************************************/
|
||||
|
||||
Scene();
|
||||
|
||||
~Scene();
|
||||
|
||||
/*************************************************************************
|
||||
* Public Methods
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* Initialize objects within the scene
|
||||
*/
|
||||
virtual void init() = 0;
|
||||
|
||||
/**
|
||||
* Function called during OpenGL drawing event.
|
||||
*
|
||||
* This function is only called when the widget is redrawn.
|
||||
*/
|
||||
virtual void draw() { privateDraw(); };
|
||||
|
||||
/**
|
||||
* Function called to update the QOpenGLWidget. Does not trigger a redraw.
|
||||
*
|
||||
* Calling this several times will still result in only one repaint.
|
||||
*/
|
||||
virtual void update() {}
|
||||
|
||||
/*************************************************************************
|
||||
* Accessors
|
||||
************************************************************************/
|
||||
|
||||
static Camera3D & getCamera() { return mCamera; }
|
||||
|
||||
static QMatrix4x4 getViewMatrix() { return mCamera.toMatrix(); }
|
||||
|
||||
static QMatrix4x4 & getProjectionMatrix() { return mProjection; }
|
||||
|
||||
inline Skybox * getSkybox() { return mSkybox; }
|
||||
|
||||
/*************************************************************************
|
||||
* Setters
|
||||
************************************************************************/
|
||||
|
||||
inline void setSkybox(Skybox * skybox) { mSkybox = skybox; }
|
||||
|
||||
private:
|
||||
/*************************************************************************
|
||||
* Private Members
|
||||
************************************************************************/
|
||||
|
||||
static Camera3D mCamera;
|
||||
static QMatrix4x4 mProjection;
|
||||
bool mInit = false;
|
||||
|
||||
/*************************************************************************
|
||||
* Private Methods
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* Handles drawing members encapsulated by this base class.
|
||||
* Child classes do not need to draw these objects manually.
|
||||
*/
|
||||
void privateDraw();
|
||||
|
||||
protected:
|
||||
/*************************************************************************
|
||||
* Protected Members
|
||||
************************************************************************/
|
||||
|
||||
/* The skybox for this scene. */
|
||||
Skybox * mSkybox {};
|
||||
/* MeshRenderers used simple geometry. */
|
||||
std::vector<MeshRenderer *> mMeshes {};
|
||||
/* Models used for storing 3D models in the scene. */
|
||||
std::vector<Model *> mModels {};
|
||||
};
|
||||
} // namespace Qtk
|
||||
|
||||
#endif // QTK_SCENE_H
|
||||
@@ -6,7 +6,7 @@
|
||||
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
|
||||
##############################################################################*/
|
||||
|
||||
#include <abstractscene.h>
|
||||
#include <scene.h>
|
||||
#include <skybox.h>
|
||||
#include <texture.h>
|
||||
|
||||
@@ -32,8 +32,8 @@ Skybox::Skybox(const std::string & name) :
|
||||
":/right.png", ":/top.png", ":/front.png", ":/left.png", ":/bottom.png",
|
||||
":/back.png", name) {}
|
||||
|
||||
Skybox::Skybox(QOpenGLTexture * cubeMap, const std::string & name) :
|
||||
mTexture(cubeMap) {
|
||||
Skybox::Skybox(QOpenGLTexture * cubeMap, const std::string & name) {
|
||||
mTexture.setTexture(cubeMap);
|
||||
init();
|
||||
}
|
||||
|
||||
@@ -49,8 +49,8 @@ void Skybox::draw() {
|
||||
mProgram.bind();
|
||||
mTexture.getOpenGLTexture().bind();
|
||||
|
||||
mProgram.setUniformValue("uProjectionMatrix", Scene::Projection());
|
||||
mProgram.setUniformValue("uViewMatrix", Scene::Camera().toMatrix());
|
||||
mProgram.setUniformValue("uProjectionMatrix", Scene::getProjectionMatrix());
|
||||
mProgram.setUniformValue("uViewMatrix", Scene::getCamera().toMatrix());
|
||||
mProgram.setUniformValue("uTexture", 0);
|
||||
glDrawElements(
|
||||
GL_TRIANGLES, mIndices.size(), GL_UNSIGNED_INT, mIndices.data());
|
||||
|
||||
24
src/skybox.h
24
src/skybox.h
@@ -21,13 +21,23 @@
|
||||
#include <texture.h>
|
||||
|
||||
namespace Qtk {
|
||||
/**
|
||||
* Skybox object for rendering a skybox within a Scene.
|
||||
* A skybox is typically implemented using a cube map texture centered around
|
||||
* the camera and projected outwards in all directions.
|
||||
*/
|
||||
class QTKAPI Skybox : protected QOpenGLFunctions {
|
||||
public:
|
||||
/*************************************************************************
|
||||
* Constructors / Destructors
|
||||
************************************************************************/
|
||||
|
||||
// Delegate this constructor to use default skybox images
|
||||
explicit Skybox(const std::string & name = "Skybox");
|
||||
|
||||
explicit Skybox(
|
||||
QOpenGLTexture * cubeMap, const std::string & name = "Skybox");
|
||||
// Constructor, Destructor
|
||||
|
||||
Skybox(
|
||||
const std::string & right, const std::string & top,
|
||||
const std::string & front, const std::string & left,
|
||||
@@ -36,11 +46,23 @@ namespace Qtk {
|
||||
|
||||
~Skybox() = default;
|
||||
|
||||
/*************************************************************************
|
||||
* Public Methods
|
||||
************************************************************************/
|
||||
|
||||
void draw();
|
||||
|
||||
private:
|
||||
/*************************************************************************
|
||||
* Private Methods
|
||||
************************************************************************/
|
||||
|
||||
void init();
|
||||
|
||||
/*************************************************************************
|
||||
* Private Members
|
||||
************************************************************************/
|
||||
|
||||
Vertices mVertices {};
|
||||
Indices mIndices {};
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ QImage * OpenGLTextureFactory::initImage(
|
||||
return loadedImage;
|
||||
}
|
||||
|
||||
QOpenGLTexture * OpenGLTextureFactory::initTexture2D(
|
||||
QOpenGLTexture * OpenGLTextureFactory::initTexture(
|
||||
const char * texture, bool flipX, bool flipY) {
|
||||
QImage * image = initImage(texture, flipX, flipY);
|
||||
auto newTexture = new QOpenGLTexture(QOpenGLTexture::Target2D);
|
||||
|
||||
158
src/texture.h
158
src/texture.h
@@ -9,30 +9,124 @@
|
||||
#ifndef QTOPENGL_TEXTURE_H
|
||||
#define QTOPENGL_TEXTURE_H
|
||||
|
||||
#include <QOpenGLShaderProgram>
|
||||
#include <QOpenGLTexture>
|
||||
#include <utility>
|
||||
|
||||
#include <qtkapi.h>
|
||||
|
||||
namespace Qtk {
|
||||
/**
|
||||
* Binds shader programs until the end of scope.
|
||||
* Does nothing if the shader program was already bound.
|
||||
*
|
||||
* See MeshRenderer::setUniform() for example.
|
||||
*/
|
||||
class QTKAPI ShaderBindScope {
|
||||
public:
|
||||
/*************************************************************************
|
||||
* Constructors / Destructors
|
||||
************************************************************************/
|
||||
|
||||
explicit ShaderBindScope(
|
||||
QOpenGLShaderProgram * program, bool was_locked) :
|
||||
mWasBound(was_locked) {
|
||||
mProgram = program;
|
||||
if(!mWasBound) {
|
||||
mProgram->bind();
|
||||
}
|
||||
}
|
||||
|
||||
~ShaderBindScope() {
|
||||
if(!mWasBound) {
|
||||
mProgram->release();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/*************************************************************************
|
||||
* Private Members
|
||||
************************************************************************/
|
||||
|
||||
QOpenGLShaderProgram * mProgram;
|
||||
bool mWasBound;
|
||||
};
|
||||
|
||||
/**
|
||||
* Factories for initializing various OpenGL textures
|
||||
*/
|
||||
class QTKAPI OpenGLTextureFactory {
|
||||
public:
|
||||
/*************************************************************************
|
||||
* Constructors / Destructors
|
||||
************************************************************************/
|
||||
~OpenGLTextureFactory() = default;
|
||||
|
||||
// QImage
|
||||
/*************************************************************************
|
||||
* Texture Factories
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* QImage factory
|
||||
*
|
||||
* @param image Path to image we want to load.
|
||||
* Can be absolute or Qt resource path.
|
||||
* @param flipX If true the image will be flipped on X axis.
|
||||
* @param flipY If true the image will be flipped on Y axis.
|
||||
* @return Pointer to an initialized QImage object.
|
||||
*/
|
||||
static QImage * initImage(
|
||||
const char * image, bool flipX = false, bool flipY = false);
|
||||
|
||||
// 2D Texture
|
||||
static QOpenGLTexture * initTexture2D(
|
||||
/**
|
||||
* QOpenGLTexture factory
|
||||
*
|
||||
* @param texture Path to texture we want to load.
|
||||
* Can be absolute or Qt resource path.
|
||||
* @param flipX If true the image will be flipped on X axis.
|
||||
* @param flipY If true the image will be flipped on Y axis.
|
||||
* @return Pointer to an initialized QOpenGLTexture object.
|
||||
*/
|
||||
static QOpenGLTexture * initTexture(
|
||||
const char * texture, bool flipX = false, bool flipY = false);
|
||||
|
||||
// Cube maps
|
||||
/**
|
||||
* Cube map factory for initializing all sides of a CubeMap.
|
||||
* All of these parameters can be absolute or Qt resource paths.
|
||||
*
|
||||
* @param right Path to image for the right side of the CubeMap.
|
||||
* @param top Path to image for the top side of the CubeMap.
|
||||
* @param front Path to image for the front side of the CubeMap.
|
||||
* @param left Path to image for the left side of the CubeMap.
|
||||
* @param bottom Path to image for the bottom side of the CubeMap.
|
||||
* @param back Path to image for the back side of the CubeMap.
|
||||
* @return Pointer to an initialized QOpenGLTexture object.
|
||||
*/
|
||||
static QOpenGLTexture * initCubeMap(
|
||||
const QImage & right, const QImage & top, const QImage & front,
|
||||
const QImage & left, const QImage & bottom, const QImage & back);
|
||||
// Overloads for cube map initialization
|
||||
|
||||
/**
|
||||
* CubeMap factory for tiling the same image on all sides.
|
||||
*
|
||||
* @param tile Path to the image we want to make into a CubeMap.
|
||||
* Can be absolute or Qt resource path.
|
||||
* @return Pointer to an initialized QOpenGLTexture object.
|
||||
*/
|
||||
static QOpenGLTexture * initCubeMap(const char * tile);
|
||||
|
||||
/**
|
||||
* Cube map factory for initializing all sides of a CubeMap.
|
||||
* All of these parameters can be absolute or Qt resource paths.
|
||||
*
|
||||
* @param right Path to image for the right side of the CubeMap.
|
||||
* @param top Path to image for the top side of the CubeMap.
|
||||
* @param front Path to image for the front side of the CubeMap.
|
||||
* @param left Path to image for the left side of the CubeMap.
|
||||
* @param bottom Path to image for the bottom side of the CubeMap.
|
||||
* @param back Path to image for the back side of the CubeMap.
|
||||
* @return Pointer to an initialized QOpenGLTexture object.
|
||||
*/
|
||||
static QOpenGLTexture * initCubeMap(
|
||||
const char * right, const char * top, const char * front,
|
||||
const char * left, const char * bottom, const char * back);
|
||||
@@ -42,48 +136,66 @@ namespace Qtk {
|
||||
OpenGLTextureFactory() = default;
|
||||
};
|
||||
|
||||
// TODO: Struct for (re)storing texture state
|
||||
/**
|
||||
* Texture object component class
|
||||
*
|
||||
* TODO: Struct for (re)storing texture state
|
||||
* A struct to store flipX, flipY and other initial state needed to copy
|
||||
*/
|
||||
class Texture {
|
||||
public:
|
||||
/*************************************************************************
|
||||
* Typedefs
|
||||
************************************************************************/
|
||||
friend class Skybox;
|
||||
|
||||
/*************************************************************************
|
||||
* Constructors / Destructors
|
||||
************************************************************************/
|
||||
|
||||
Texture() = default;
|
||||
|
||||
Texture(const Texture & value) {
|
||||
mOpenGLTexture = OpenGLTextureFactory::initTexture2D(value.mPath);
|
||||
mOpenGLTexture = OpenGLTextureFactory::initTexture(value.mPath);
|
||||
mPath = value.mPath;
|
||||
}
|
||||
|
||||
explicit Texture(
|
||||
const char * path, bool flipX = false, bool flipY = false) :
|
||||
mOpenGLTexture(
|
||||
OpenGLTextureFactory::initTexture2D(path, flipX, flipY)),
|
||||
mOpenGLTexture(OpenGLTextureFactory::initTexture(path, flipX, flipY)),
|
||||
mPath(path) {}
|
||||
|
||||
explicit Texture(QOpenGLTexture * texture) : mOpenGLTexture(texture) {}
|
||||
|
||||
~Texture() { mOpenGLTexture->destroy(); }
|
||||
|
||||
/*************************************************************************
|
||||
* Accessors
|
||||
************************************************************************/
|
||||
|
||||
[[nodiscard]] inline QOpenGLTexture & getOpenGLTexture() const {
|
||||
return *mOpenGLTexture;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline std::string getPath() const { return mPath; }
|
||||
|
||||
/*************************************************************************
|
||||
* Setters
|
||||
************************************************************************/
|
||||
|
||||
void setTexture(
|
||||
const std::string & path, bool flipX = false, bool flipY = false) {
|
||||
mOpenGLTexture =
|
||||
OpenGLTextureFactory::initTexture2D(path.data(), flipX, flipY);
|
||||
OpenGLTextureFactory::initTexture(path.data(), flipX, flipY);
|
||||
mPath = path.data();
|
||||
}
|
||||
|
||||
void setTexture(
|
||||
const char * path, bool flipX = false, bool flipY = false) {
|
||||
mOpenGLTexture =
|
||||
OpenGLTextureFactory::initTexture2D(path, flipX, flipY);
|
||||
mOpenGLTexture = OpenGLTextureFactory::initTexture(path, flipX, flipY);
|
||||
mPath = path;
|
||||
}
|
||||
|
||||
// TODO: This is unsafe because we don't have a path. Encapsulate it.
|
||||
inline void setTexture(QOpenGLTexture * texture) {
|
||||
mOpenGLTexture = texture;
|
||||
}
|
||||
|
||||
virtual inline void setCubeMap(const char * path) {
|
||||
mOpenGLTexture = OpenGLTextureFactory::initCubeMap(path);
|
||||
mPath = path;
|
||||
@@ -103,12 +215,24 @@ namespace Qtk {
|
||||
right, top, front, left, bottom, back);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Public Methods
|
||||
************************************************************************/
|
||||
|
||||
[[nodiscard]] inline bool hasTexture() const {
|
||||
return mOpenGLTexture != Q_NULLPTR;
|
||||
}
|
||||
|
||||
private:
|
||||
/*************************************************************************
|
||||
* Private Members
|
||||
************************************************************************/
|
||||
inline void setTexture(QOpenGLTexture * texture) {
|
||||
mOpenGLTexture = texture;
|
||||
}
|
||||
|
||||
QOpenGLTexture * mOpenGLTexture = Q_NULLPTR;
|
||||
/* Path to this texture on disk or Qt resource. */
|
||||
const char * mPath {};
|
||||
};
|
||||
|
||||
|
||||
@@ -23,15 +23,22 @@
|
||||
#include <qtkapi.h>
|
||||
|
||||
namespace Qtk {
|
||||
/**
|
||||
* Transform3D class to represent and modify object position in 3D space.
|
||||
*/
|
||||
class QTKAPI Transform3D {
|
||||
public:
|
||||
// Constructors
|
||||
/*************************************************************************
|
||||
* Constructors, Destructors
|
||||
************************************************************************/
|
||||
|
||||
inline Transform3D() :
|
||||
m_dirty(true), mScale(1.0f, 1.0f, 1.0f),
|
||||
mTranslation(0.0f, 0.0f, 0.0f) {}
|
||||
|
||||
//
|
||||
// Transformations
|
||||
/*************************************************************************
|
||||
* Transformations
|
||||
************************************************************************/
|
||||
|
||||
void translate(const QVector3D & dt);
|
||||
|
||||
@@ -72,8 +79,9 @@ namespace Qtk {
|
||||
grow(QVector3D(factor, factor, factor));
|
||||
}
|
||||
|
||||
//
|
||||
// Setters
|
||||
/*************************************************************************
|
||||
* Setters
|
||||
************************************************************************/
|
||||
|
||||
// Set object position
|
||||
void setTranslation(const QVector3D & t);
|
||||
@@ -102,8 +110,9 @@ namespace Qtk {
|
||||
setRotation(QQuaternion::fromAxisAndAngle(ax, ay, az, angle));
|
||||
}
|
||||
|
||||
//
|
||||
// Accessors
|
||||
/*************************************************************************
|
||||
* Getters
|
||||
************************************************************************/
|
||||
|
||||
[[nodiscard]] inline const QVector3D & getTranslation() const {
|
||||
return mTranslation;
|
||||
@@ -121,9 +130,17 @@ namespace Qtk {
|
||||
[[nodiscard]] QVector3D getUp() const;
|
||||
[[nodiscard]] QVector3D getRight() const;
|
||||
|
||||
/*************************************************************************
|
||||
* Public members
|
||||
************************************************************************/
|
||||
|
||||
static const QVector3D LocalForward, LocalUp, LocalRight;
|
||||
|
||||
private:
|
||||
/*************************************************************************
|
||||
* Private members
|
||||
************************************************************************/
|
||||
|
||||
QVector3D mTranslation;
|
||||
QQuaternion mRotation;
|
||||
QVector3D mScale;
|
||||
|
||||
Reference in New Issue
Block a user