restructured project to encapsulate backend into library

This commit is contained in:
Lauchmelder 2021-12-21 15:51:54 +01:00
parent 01f5a26aa6
commit 19cae22aba
12 changed files with 29 additions and 11 deletions

View file

@ -0,0 +1,36 @@
#pragma once
#include <glad/glad.h>
#include "VertexArrayObject.hpp"
#include "Shader.hpp"
enum class PrimitiveType
{
Lines = GL_LINES,
LineStrip = GL_LINE_STRIP,
LineLoop = GL_LINE_LOOP,
Triangles = GL_TRIANGLES,
TriangleStrip = GL_TRIANGLE_STRIP,
TriangleFan = GL_TRIANGLE_FAN
};
class Drawable
{
public:
Drawable(const Drawable& other) = delete;
void operator=(const Drawable& other) = delete;
virtual void InitializeShader() = 0;
void Render();
void SetPrimitiveType(PrimitiveType type);
protected:
Drawable() {}
protected:
VertexArrayObject vao;
Shader shader;
PrimitiveType type = PrimitiveType::Triangles;
};

View file

@ -0,0 +1,71 @@
#pragma once
#include <map>
#include <memory>
/**
* Some objects should only exist once but be available to multiple objects (e.g. multiple
* models sharing the same VAO and shaders. Any object can register objects here and other
* objects can then retrieve them if they have the ID.
*
* Objects are stored and returned as shared_ptr's, so even if a part of the program deletes
* an object from the manager, any part of the program that has the objects stored in them will
* not break and still work. But realistically this shouldn't happen in the first place.
* As a consequence, even if no objects are using an object stored in here it will continue to
* exist.
*/
template<typename Type>
class ObjectManager
{
public:
static ObjectManager<Type>& GetInstance()
{
static ObjectManager<Type> instance;
return instance;
}
public:
ObjectManager(const ObjectManager<Type>&) = delete;
void operator=(const ObjectManager<Type>&) = delete;
/**
* Add new (existing) object to manager
*/
inline void Register(unsigned int id, std::shared_ptr<Type> obj)
{
objects.insert(std::make_pair(id, obj));
}
/**
* Remove object from manager
*/
inline void Delete(unsigned int id)
{
objects.erase(id);
}
/**
* Retrieve object from manager
*/
inline std::shared_ptr<Type> Get(unsigned int id)
{
auto it = objects.find(id);
if (it == objects.end())
return nullptr;
return it->second;
}
private:
ObjectManager() {}
private:
std::map<unsigned int, std::shared_ptr<Type>> objects;
};
class AbstractShader;
class AbstractVertexArrayObject;
typedef ObjectManager<AbstractVertexArrayObject> VAOManager;
typedef ObjectManager<AbstractShader> ShaderManager;

View file

@ -0,0 +1,38 @@
#pragma once
#include <glm/glm.hpp>
#include <string>
#include <memory>
#include <functional>
class AbstractShader
{
friend class ShaderFactory;
public:
AbstractShader(const std::string& vertexShader, const std::string& fragmentShader);
AbstractShader(const AbstractShader& other) = delete;
~AbstractShader();
inline bool Good() { return id != 0; }
void Use();
void SetUniform(const std::string& name, const glm::mat4& value);
private:
unsigned int id;
bool recording = false;
};
typedef std::shared_ptr<AbstractShader> Shader;
class ShaderFactory
{
public:
inline static Shader Produce(const std::string& vertexShader, const std::string& fragmentShader)
{
return std::make_shared<AbstractShader>(vertexShader, fragmentShader);
}
};

View file

@ -0,0 +1,32 @@
#pragma once
#include <glm/glm.hpp>
#include <glm/gtx/quaternion.hpp>
class Transformable
{
public:
Transformable();
const glm::vec3& GetPosition();
void SetPosition(const glm::vec3& pos);
void Move(const glm::vec3& direction);
const glm::vec3 GetRotation();
void SetRotation(const glm::vec3& axis, float angle);
void SetRotation(const glm::vec3& eulerAngles);
void Rotate(const glm::vec3& axis, float angle);
const glm::vec3& GetScale();
void SetScale(const glm::vec3& scale);
void Scale(const glm::vec3& factor);
private:
void CalculateTransformationMatrix();
protected:
glm::mat4 transformation;
glm::vec3 position, scale;
glm::quat orientation;
};

View file

@ -0,0 +1,58 @@
#pragma once
#include <vector>
#include <memory>
// struct representing an OpenGL attribute pointer
struct VertexAttribute
{
int size;
unsigned int type;
bool normalized;
unsigned int stride;
const void* pointer;
};
// Useful abbreviations
typedef std::vector<float> VertexArray;
typedef std::vector<unsigned int> IndexArray;
typedef std::vector<VertexAttribute> Layout;
// OpenGL Buffer usages (I turned them into an enum so it's easier to know what options exist)
enum class Usage
{
Static, Stream, Dynamic
};
// VAO structure that sets up the buffers and deletes them at the end of the lifecycle
class AbstractVertexArrayObject
{
friend class VAOFactory;
public:
AbstractVertexArrayObject() = delete;
AbstractVertexArrayObject(const VertexArray& vertices, const IndexArray& indices, const Layout& layout, Usage usage);
~AbstractVertexArrayObject();
void Render(unsigned int mode = 4);
private:
unsigned int vao, vbo, ebo;
size_t indexCount;
};
// You cannot actually create this VAO, you are forced to use a shared pointer
// so the buffers dont get accidentally deleted while another obejct is potentially still using it.
// I find this to be very important since VAOs are supposed to be shared between copies of objects
// if they have the same model.
typedef std::shared_ptr<AbstractVertexArrayObject> VertexArrayObject;
// Factory for creating said shared pointers.
class VAOFactory
{
public:
static VertexArrayObject Produce(const VertexArray& vertices, const IndexArray& indices, const Layout& layout, Usage usage = Usage::Static)
{
return std::make_shared<AbstractVertexArrayObject>(vertices, indices, layout, usage);
}
};