diff --git a/src/main.cpp b/src/main.cpp index 9c725a1..4cbb8d9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,10 +28,10 @@ static Scene scene; static Camera camera(scene); static float camera_angles_x = 0; -static Model *protagonist; -static Model *suzanne; -static Model *teapot; -static Model *bunny; +static const Model *protagonist; +static const Model *suzanne; +static const Model *teapot; +static const Model *bunny; static Object *protagonist1; static Object *suzanne1; @@ -59,22 +59,22 @@ int main() glfwSetKeyCallback(on_key); emscripten_set_mousemove_callback(nullptr, nullptr, false, on_em_mousemove); - Program program("textured"); - program.use(); + const Program *program = Store().load("textured"); + program->use(); - mvp_uniform = program.get_uniform_location("mvp"); - local_modelview_uniform = program.get_uniform_location("local_modelview"); + mvp_uniform = program->get_uniform_location("mvp"); + local_modelview_uniform = program->get_uniform_location("local_modelview"); - texture_uniform = program.get_uniform_location("texture"); + texture_uniform = program->get_uniform_location("texture"); glUniform1i(texture_uniform, 0); camera.projection = glm::perspective(45.0f, (float)640 / (float)480, 0.1f, 10.0f); camera.position.z = 2; - protagonist = new Model("protagonist.obj"); - suzanne = new Model("suzanne.obj"); - teapot = new Model("teapot.obj"); - bunny = new Model("bunny.obj"); + protagonist = Store().load("protagonist.obj"); + suzanne = Store().load("suzanne.obj"); + teapot = Store().load("teapot.obj"); + bunny = Store().load("bunny.obj"); protagonist1 = new Object(*protagonist); protagonist1->position.z = 4; diff --git a/src/material.hpp b/src/material.hpp index d47094d..8f72063 100644 --- a/src/material.hpp +++ b/src/material.hpp @@ -8,7 +8,7 @@ class Material public: inline void use() const; - Texture *texture; + const Texture *texture; }; void Material::use() const diff --git a/src/model.cpp b/src/model.cpp index 95b03d7..7e5599e 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -5,9 +5,14 @@ #include #include +const std::string Model::filename(const std::string &name) +{ + return "/data/models/" + name; +} + Model::Model(const std::string &name) { - std::ifstream file("/data/models/" + name, std::ios::in); + std::ifstream file(filename(name), std::ios::in); Mtllib *mtllib = nullptr; @@ -76,7 +81,7 @@ Model::Model(const std::string &name) else if (line.substr(0, 7) == "mtllib ") { - mtllib = new Mtllib(line.substr(7)); + mtllib = (Mtllib*)Store().load(line.substr(7)); } else if (line.substr(0, 7) == "usemtl ") diff --git a/src/model.hpp b/src/model.hpp index d040958..311876a 100644 --- a/src/model.hpp +++ b/src/model.hpp @@ -1,6 +1,7 @@ #ifndef _MODEL_HPP_ #define _MODEL_HPP_ +#include "store.hpp" #include "gl.hpp" #include "material.hpp" @@ -9,10 +10,16 @@ #include -class Model +class Model: + public Store::Resource { -public: + friend class Store; + Model(const std::string &name); + + static const std::string filename(const std::string &name); + +public: void draw() const; private: @@ -28,7 +35,7 @@ private: std::vector elements; GLuint id; - Material *_material; + const Material *_material; static GLuint create_array_buffer(GLenum type, GLsizeiptr size, const GLvoid *data); }; diff --git a/src/mtllib.cpp b/src/mtllib.cpp index e6a5f93..ee7959d 100644 --- a/src/mtllib.cpp +++ b/src/mtllib.cpp @@ -3,9 +3,14 @@ #include #include +const std::string Mtllib::filename(const std::string &name) +{ + return "/data/materials/" + name; +} + Mtllib::Mtllib(const std::string &name) { - std::ifstream file("/data/materials/" + name, std::ios::in); + std::ifstream file(filename(name), std::ios::in); Material *material = nullptr; @@ -23,7 +28,7 @@ Mtllib::Mtllib(const std::string &name) else if (line.substr(0, 7) == "map_Kd ") { - material->texture = new Texture(line.substr(7).c_str()); + material->texture = Store().load(line.substr(7)); } } } diff --git a/src/mtllib.hpp b/src/mtllib.hpp index 1db822c..d6f92ee 100644 --- a/src/mtllib.hpp +++ b/src/mtllib.hpp @@ -1,17 +1,23 @@ #ifndef _MTLLIB_HPP_ #define _MTLLIB_HPP_ +#include "store.hpp" #include "material.hpp" #include #include -class Mtllib +class Mtllib: + public Store::Resource { -public: + friend class Store; + Mtllib(const std::string &name); - std::map materials; + static const std::string filename(const std::string &name); + +public: + std::map materials; }; #endif // _MTLLIB_HPP_ diff --git a/src/program.cpp b/src/program.cpp index dd254ca..f8cbd81 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -2,12 +2,16 @@ #include "shader.hpp" -#include #include -Program::Program(const char *const name) +const std::string Program::filename(const std::string &name) { - const std::string path = std::string("/data/shaders/") + name + '/'; + return "/data/shaders/" + name; +} + +Program::Program(const std::string &name) +{ + const std::string path = filename(name) + '/'; const Shader vertex_shader = Shader(GL_VERTEX_SHADER, (path + "vertex.glsl").c_str()); const Shader fragment_shader = Shader(GL_FRAGMENT_SHADER, (path + "fragment.glsl").c_str()); diff --git a/src/program.hpp b/src/program.hpp index 0d7fd43..509b828 100644 --- a/src/program.hpp +++ b/src/program.hpp @@ -1,12 +1,21 @@ #ifndef _PROGRAM_HPP_ #define _PROGRAM_HPP_ +#include "store.hpp" #include "gl.hpp" -class Program +#include + +class Program: + public Store::Resource { + friend class Store; + + Program(const std::string &name); + + static const std::string filename(const std::string &name); + public: - Program(const char *name); void use() const; GLuint get_uniform_location(const GLchar *name) const; diff --git a/src/store.hpp b/src/store.hpp new file mode 100644 index 0000000..e8c313f --- /dev/null +++ b/src/store.hpp @@ -0,0 +1,40 @@ +#ifndef _STORE_HPP_ +#define _STORE_HPP_ + +#include +#include +#include + +class Store +{ +public: + class Resource + { + friend class Store; + + __attribute__((unused)) // Used by friend class Store + unsigned long _ref_count = 0; + }; + + template + const T *load(const std::string &name); + +private: + std::map _resources; +}; + +template +const T *Store::load(const std::string &name) +{ + static_assert(std::is_convertible::value + && !std::is_same::value, + "Store can load only Resource's children"); + + if (_resources.find(name) == _resources.end()) + _resources[T::filename(name)] = new T(name); + + _resources[T::filename(name)]->_ref_count++; + return (T*)_resources[T::filename(name)]; +} + +#endif // _STORE_HPP_ diff --git a/src/texture.cpp b/src/texture.cpp index 6108ceb..eb531f0 100644 --- a/src/texture.cpp +++ b/src/texture.cpp @@ -4,9 +4,14 @@ #include +const std::string Texture::filename(const std::string &name) +{ + return "/data/textures/" + name; +} + Texture::Texture(const std::string &name) { - SDL_Surface *surface = IMG_Load(("/data/textures/" + name).c_str()); + SDL_Surface *surface = IMG_Load(filename(name).c_str()); glGenTextures(1, &_id); glBindTexture(GL_TEXTURE_2D, _id); diff --git a/src/texture.hpp b/src/texture.hpp index 99b4312..d43f310 100644 --- a/src/texture.hpp +++ b/src/texture.hpp @@ -1,14 +1,22 @@ #ifndef _TEXTURE_HPP_ #define _TEXTURE_HPP_ +#include "store.hpp" #include "gl.hpp" #include -class Texture +class Texture: + public Store::Resource { -public: + friend class Store; + Texture(const std::string &name); + + static const std::string filename(const std::string &name); + +public: + void use() const; private: