vOOlkan
An object oriented approach to Vulkan
Model.h
Go to the documentation of this file.
1#ifndef VULKAN_MODEL
2#define VULKAN_MODEL
3
4#include <glm/glm.hpp>
5#include <glm/gtc/matrix_transform.hpp>
6#include <glm/gtc/quaternion.hpp>
7#include <vector>
8#include <tuple>
9
10#include "VertexInput.h"
11#include "ModelLoader.h"
12#include "Cinematicable.h"
13#include "Foundations.h"
14#include "Hitbox.h"
15#include "KeyboardListener.h"
16
17
18namespace Vulkan::Objects {
19
20 template<typename V>
21 concept IsVertex = requires(V v) {
22 {V::getDescriptors(0)} -> std::same_as<std::pair<VkVertexInputBindingDescription, std::vector<VkVertexInputAttributeDescription>>>;
23 };
24
25
26 template<IsVertex Vertex, typename... Structs>
28
29 using Matrices = struct {
30 alignas(16) glm::mat4 mvp;
31 alignas(16) glm::mat4 model;
32 alignas(16) glm::mat4 normals;
33 };
34
35 public:
36
37 Model(std::unique_ptr<Vulkan::Physics::Hitbox> hitbox, glm::vec3 rotationEuler, Vertex, std::string pathToModel, Structs... uniforms) : vertices{}, indexes{}, uniforms{ Matrices{}, uniforms... }, hitbox{ std::move(hitbox) }, reactToKeyPress{ [](Model&, int) {} } {
38 ModelLoader<Vertex>::loadModel(pathToModel, vertices, indexes);
39 rotation = glm::quat(rotationEuler);
40 }
41
42
43 Model(glm::vec3 rotationEuler, float scale, Physics::Position position, std::vector<Vertex> vertices, std::vector<uint32_t> indexes, Structs... uniforms) : vertices{ vertices }, indexes{ indexes }, uniforms{ Matrices{}, uniforms... }, hitbox{}, reactToKeyPress{ [](Model&, int) {} } {
44 rotation = glm::quat(rotationEuler);
45 hitbox = std::make_unique<Vulkan::Physics::Hitbox>(position, scale);
46 }
47
48
49 void setKeyPressResponse(std::function<void(Model&, int)> reactToKeyPress) {
50 this->reactToKeyPress = reactToKeyPress;
51 }
52
53
54 const std::vector<Vertex>& getVertices() const {
55 return vertices;
56 }
57
58
59 void setVertices(std::vector<Vertex> vertices) {
60 this->vertices = vertices;
61 }
62
63
64 const std::vector<uint32_t>& getIndexes() const {
65 return indexes;
66 }
67
68
69 Model& rotateModel(float angle, glm::vec3 axis) {
70 rotation = glm::rotate(rotation, angle, axis);
71 return *this;
72 }
73
74
75 const glm::mat4& calculateModelMatrix() const {
76 return glm::translate(glm::mat4{ 1.0f }, glm::vec3(hitbox->getPosition())) *
77 glm::scale(glm::mat4{ 1.0f }, glm::vec3{ hitbox->getScaleFactor() }) *
78 glm::mat4{ hitbox->getRotation() * rotation};
79 }
80
81
82 const glm::mat4& calculateNormalModelMatrix() const {
83 return glm::inverse(glm::transpose(calculateModelMatrix()));
84 }
85
86
87 const glm::mat4& calculateMvpMatrix(const glm::mat4& viewMatrix, const glm::mat4& projectionMatrix) const {
88 glm::mat4 modelMatrix = calculateModelMatrix();
89 return projectionMatrix * viewMatrix * modelMatrix;
90 }
91
92
93 std::tuple<Matrices, Structs...>& getUniforms(const glm::mat4& viewMatrix, const glm::mat4& projectionMatrix) {
94 std::get<0>(uniforms).mvp = calculateMvpMatrix(viewMatrix, projectionMatrix);
95 std::get<0>(uniforms).model = calculateModelMatrix();
96 std::get<0>(uniforms).normals = calculateNormalModelMatrix();
97 return uniforms;
98 }
99
100
101 template<unsigned int I>
102 auto& getUniform(const glm::mat4& viewMatrix = glm::mat4{}, const glm::mat4& projectionMatrix = glm::mat4{}) {
103 return std::get<I>(uniforms);
104 }
105
106 template<>
107 auto& getUniform<0>(const glm::mat4& viewMatrix, const glm::mat4& projectionMatrix) {
108 std::get<0>(uniforms) = calculateMvpMatrix(viewMatrix, projectionMatrix);
109 return std::get<0>(uniforms);
110 }
111
112
114 return *hitbox;
115 }
116
117
118 void onKeyPress(int keyPressed) override {
119 reactToKeyPress(*this, keyPressed);
120 }
121
122
123 private:
124 std::vector<Vertex> vertices;
125 std::vector<uint32_t> indexes;
126 std::tuple<Matrices, Structs...> uniforms;
127
128 glm::quat rotation; //in this simplified version of the physics (2D) a model can have a different rotation than the one of its hitbox
129
130 std::unique_ptr<Vulkan::Physics::Hitbox> hitbox;
131
132 std::function<void(Model&, int)> reactToKeyPress;
133 };
134}
135
136#endif
Definition: ModelLoader.h:13
Definition: Model.h:27
std::tuple< Matrices, Structs... > & getUniforms(const glm::mat4 &viewMatrix, const glm::mat4 &projectionMatrix)
Definition: Model.h:93
Model(glm::vec3 rotationEuler, float scale, Physics::Position position, std::vector< Vertex > vertices, std::vector< uint32_t > indexes, Structs... uniforms)
Definition: Model.h:43
Vulkan::Physics::Hitbox & operator+()
Definition: Model.h:113
const glm::mat4 & calculateMvpMatrix(const glm::mat4 &viewMatrix, const glm::mat4 &projectionMatrix) const
Definition: Model.h:87
void onKeyPress(int keyPressed) override
Definition: Model.h:118
const std::vector< uint32_t > & getIndexes() const
Definition: Model.h:64
const std::vector< Vertex > & getVertices() const
Definition: Model.h:54
Model(std::unique_ptr< Vulkan::Physics::Hitbox > hitbox, glm::vec3 rotationEuler, Vertex, std::string pathToModel, Structs... uniforms)
Definition: Model.h:37
auto & getUniform(const glm::mat4 &viewMatrix=glm::mat4{}, const glm::mat4 &projectionMatrix=glm::mat4{})
Definition: Model.h:102
void setVertices(std::vector< Vertex > vertices)
Definition: Model.h:59
const glm::mat4 & calculateNormalModelMatrix() const
Definition: Model.h:82
void setKeyPressResponse(std::function< void(Model &, int)> reactToKeyPress)
Definition: Model.h:49
Model & rotateModel(float angle, glm::vec3 axis)
Definition: Model.h:69
const glm::mat4 & calculateModelMatrix() const
Definition: Model.h:75
A Hitbox is a Cinematicable object which can directly interact with other objects upon collision.
Definition: Hitbox.h:19
Definition: Foundations.h:187
Definition: KeyboardListener.h:13
Definition: Model.h:21
Definition: Camera.h:11