abstract base class for GL objects

This commit is contained in:
frank 2021-09-24 02:43:38 -04:00
parent 1a4b8507e3
commit 6adac9806f
10 changed files with 157 additions and 77 deletions

View File

@ -50,7 +50,7 @@ CFLAGS := -Wall -O0 -c -I$(SB_LIB_DIR) -I$(SB_SRC_DIR) $(shell $(SDLCONFIG) --cf
CPP_FLAGS := $(CFLAGS) --std=c++17
LFLAGS := $(shell $(SDLCONFIG) --libs) -lpthread
SB_H_FILES := $(wildcard $(addprefix $(SB_SRC_DIR),*.hpp))
SB_O_FILES := $(filter-out $(addprefix $(SB_SRC_DIR),filesystem.o),$(SB_H_FILES:.hpp=.o))
SB_O_FILES := $(filter-out $(addprefix $(SB_SRC_DIR),filesystem.o GLObject.o),$(SB_H_FILES:.hpp=.o))
SRC_H_FILES := $(wildcard $(addprefix $(SRC_DIR),*.hpp))
SRC_O_FILES := $(SRC_H_FILES:.hpp=.o)
@ -77,6 +77,7 @@ $(SB_SRC_DIR)Box.o : $(addprefix $(SB_SRC_DIR),extension.hpp Segment.hpp)
$(SB_SRC_DIR)Segment.o : $(addprefix $(SB_SRC_DIR),extension.hpp Box.hpp)
$(SB_SRC_DIR)Pixels.o : $(addprefix $(SB_SRC_DIR),Box.hpp extension.hpp)
$(SB_SRC_DIR)Audio.o : $(addprefix $(SB_SRC_DIR),Node.hpp Display.hpp Configuration.hpp Box.hpp filesystem.hpp extension.hpp)
$(SB_SRC_DIR)Texture.o : $(addprefix $(SB_SRC_DIR),GLObject.hpp)
$(SRC_DIR)Squircle.o : $(SB_H_FILES)
%.o : %.cpp %.hpp
$(CPPC) $(CPP_FLAGS) $< -c -o $@

29
src/GLObject.cpp Normal file
View File

@ -0,0 +1,29 @@
#include "GLObject.hpp"
/* A deleter function is required for freeing the memory allocated to the object (this could be, for example,
* glDeleteTextures for a Texture object, or a custom function that does something in addition to calling
* the appropriate GL deleter function) */
GLObject::GLObject(std::function<void(GLuint*)> deleter)
{
this->deleter = deleter;
}
/* Set the shared pointer to point to a new GLuint with specified ID value */
void GLObject::id(GLuint id)
{
/* The deleter will be called when the object and all of its copies have gone out of scope */
object_id = std::shared_ptr<GLuint>(new GLuint, deleter);
*object_id = id;
}
/* Return the GL ID that was set for this object */
GLuint GLObject::id() const
{
return *object_id;
}
/* Returns true if an ID has been generated */
bool GLObject::generated() const
{
return static_cast<bool>(object_id);
};

53
src/GLObject.hpp Normal file
View File

@ -0,0 +1,53 @@
/* /\ +--------------------------------------------------------------+
____/ \____ /| - zlib/MIT/Unlicenced game framework licensed to freely use, |
\ / / | copy, modify and sell without restriction |
+--\ ^__^ /--+ | |
| ~/ \~ | | - originally created at [http://nugget.fun] |
| ~~~~~~~~~~~~ | +--------------------------------------------------------------+
| SPACE ~~~~~ | /
| ~~~~~~~ BOX |/
+--------------+
[GLObject.hpp]
The abstract GLObject class is meant to be inherited by specific types of OpenGL objects,
for example Textures or Buffer objects. It stores the object's ID and declares virtual
functions for generating, binding, and destroying the object.
*/
#ifndef GLObject_h_
#define GLObject_h_
#include <iostream>
#include <memory>
#include <functional>
/* include Open GL */
#if defined(__EMSCRIPTEN__)
#include <GL/glew.h>
#else
#include "glew/glew.h"
#endif
class GLObject
{
protected:
std::shared_ptr<GLuint> object_id = nullptr;
std::function<void(GLuint*)> deleter = nullptr;
public:
GLObject(std::function<void(GLuint*)>);
virtual void generate() = 0;
virtual void bind() const = 0;
void id(GLuint);
GLuint id() const;
bool generated() const;
virtual ~GLObject() = default;
};
#endif

View File

@ -35,9 +35,11 @@
#include "filesystem.hpp"
#include "extension.hpp"
struct FramerateIndicator : Sprite
class FramerateIndicator : public Sprite
{
public:
FramerateIndicator(Node*);
void respond(SDL_Event&);
SDL_Surface* get_surface();

View File

@ -6,7 +6,7 @@
#include "Color.hpp"
#include "extension.hpp"
struct Sprite;
class Sprite;
struct Pixels
{

View File

@ -8,7 +8,7 @@
#include "glm/vec2.hpp"
class Box;
struct Sprite;
class Sprite;
class Segment
{

View File

@ -1,3 +1,4 @@
#include "Game.hpp"
#include "Sprite.hpp"
Sprite::Sprite() : Sprite(nullptr) {}
@ -115,12 +116,12 @@ const std::vector<SDL_Texture*>& Sprite::get_frames() const
return frames;
}
Frameset& Sprite::get_all_frames_frameset()
Sprite::Frameset& Sprite::get_all_frames_frameset()
{
return framesets[get_configuration()["animation"]["all-frames-frameset-name"]];
}
Frameset& Sprite::add_frameset(std::string name)
Sprite::Frameset& Sprite::add_frameset(std::string name)
{
if (framesets.find(name) == framesets.end())
{
@ -129,7 +130,7 @@ Frameset& Sprite::add_frameset(std::string name)
return framesets[name];
}
Frameset& Sprite::set_frameset(std::string name)
Sprite::Frameset& Sprite::set_frameset(std::string name)
{
current_frameset_name = name;
frame_animation.set_frame_length(get_current_frameset().get_frame_length());
@ -140,12 +141,12 @@ Frameset& Sprite::set_frameset(std::string name)
return get_current_frameset();
}
Frameset& Sprite::get_current_frameset()
Sprite::Frameset& Sprite::get_current_frameset()
{
return framesets.at(current_frameset_name);
}
const Frameset& Sprite::get_current_frameset() const
const Sprite::Frameset& Sprite::get_current_frameset() const
{
return framesets.at(current_frameset_name);
}
@ -933,17 +934,17 @@ void Sprite::set_to_deallocate_memory()
leave_memory_allocated = false;
}
Frameset::Frameset() : Frameset(NULL) {}
Sprite::Frameset::Frameset() : Frameset(NULL) {}
Frameset::Frameset(Sprite* sprite) : sprite(sprite) {}
Sprite::Frameset::Frameset(Sprite* sprite) : sprite(sprite) {}
void Frameset::add_frame_indicies(int index)
void Sprite::Frameset::add_frame_indicies(int index)
{
order.push_back(index);
set_size();
}
void Frameset::set_frame_length(float length)
void Sprite::Frameset::set_frame_length(float length)
{
frame_length = length;
if (&sprite->get_current_frameset() == this)
@ -952,38 +953,38 @@ void Frameset::set_frame_length(float length)
}
}
float Frameset::get_frame_length() const
float Sprite::Frameset::get_frame_length() const
{
return frame_length;
}
void Frameset::reset()
void Sprite::Frameset::reset()
{
set_order_index(0);
}
void Frameset::clear()
void Sprite::Frameset::clear()
{
order.clear();
reset();
}
int Frameset::get_order_index() const
int Sprite::Frameset::get_order_index() const
{
return order_index;
}
void Frameset::set_order_index(int index)
void Sprite::Frameset::set_order_index(int index)
{
order_index = index;
}
int Frameset::get_current_frame_index() const
int Sprite::Frameset::get_current_frame_index() const
{
return order[get_order_index()];
}
glm::vec2 Frameset::measure() const
glm::vec2 Sprite::Frameset::measure() const
{
glm::vec2 s(0, 0);
int w, h;
@ -999,22 +1000,22 @@ glm::vec2 Frameset::measure() const
return s;
}
void Frameset::set_size()
void Sprite::Frameset::set_size()
{
set_size(measure());
}
void Frameset::set_size(const glm::vec2& s)
void Sprite::Frameset::set_size(const glm::vec2& s)
{
size = s;
}
const glm::vec2& Frameset::get_size() const
const glm::vec2& Sprite::Frameset::get_size() const
{
return size;
}
void Frameset::step()
void Sprite::Frameset::step()
{
if (order.size() > 0)
{
@ -1022,22 +1023,22 @@ void Frameset::step()
}
}
void Frameset::increment_index()
void Sprite::Frameset::increment_index()
{
increment_index(reversed ? -1 : 1);
}
void Frameset::increment_index(int increment)
void Sprite::Frameset::increment_index(int increment)
{
set_order_index((order_index + increment) % order.size());
}
int Frameset::get_frame_count() const
int Sprite::Frameset::get_frame_count() const
{
return order.size();
}
void Frameset::reverse()
void Sprite::Frameset::reverse()
{
reversed = !reversed;
}

View File

@ -9,22 +9,23 @@
#include <utility>
#include <list>
#include <stdexcept>
#include "SDL.h"
#include "SDL_image.h"
#include "Node.hpp"
#include "Box.hpp"
#include "Animation.hpp"
#include "Color.hpp"
class Game;
struct Frameset;
struct Sprite : Node
class Sprite : public Node
{
struct Child;
public:
class Frameset;
class Child;
std::vector<SDL_Texture*> frames;
std::vector<fs::path> frame_paths;
std::vector<Box> boxes = {{{0, 0}, {0, 0}}};
@ -145,12 +146,14 @@ struct Sprite : Node
void set_to_leave_memory_allocated();
void set_to_deallocate_memory();
virtual std::string class_name() const { return "Sprite"; }
~Sprite() { unload(); }
};
struct Sprite::Child
class Sprite::Child
{
public:
std::string name;
Sprite sprite;
@ -160,11 +163,14 @@ struct Sprite::Child
{
return this->name == name;
}
};
struct Frameset
class Sprite::Frameset
{
public:
Sprite* sprite;
std::vector<int> order;
int order_index = 0;
@ -204,7 +210,6 @@ struct Frameset
};
#include "Pixels.hpp"
#include "Game.hpp"
#include "extension.hpp"
#endif

View File

@ -1,7 +1,10 @@
#include "Texture.hpp"
/* Have to pass our deleter to abstract base class at instantiation */
Texture::Texture() : GLObject(texture_deleter) {}
/* If an image path is passed at creation, the path will be stored in the class for later loading */
Texture::Texture(fs::path path)
Texture::Texture(fs::path path) : Texture()
{
associate(path);
}
@ -13,12 +16,18 @@ void Texture::associate(fs::path path)
this->path = path;
}
/* Generate a GL_TEXTURE_2D texture and allocate GL_RGB8 storage for the given size */
void Texture::generate(glm::vec2 size)
/* Generate an ID for this Texture and save it */
void Texture::generate()
{
GLuint id;
glGenTextures(1, &id);
this->id(id);
}
/* Generate a GL_TEXTURE_2D texture ID and allocate GL_RGB8 storage for the given size */
void Texture::generate(glm::vec2 size)
{
generate();
bind();
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, size.x, size.y);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@ -26,12 +35,6 @@ void Texture::generate(glm::vec2 size)
Game::log_gl_errors();
}
/* Returns true if an ID has been generated for this Texture */
bool Texture::generated() const
{
return static_cast<bool>(texture_id);
}
/* When called with no parameters, use the stored path variable */
void Texture::load()
{
@ -92,19 +95,6 @@ void Texture::load(void* pixels, GLenum format, GLenum type)
}
}
/* Set the shared pointer to point to a new GLuint with specified ID value */
void Texture::id(GLuint id)
{
texture_id = std::shared_ptr<GLuint>(new GLuint, Texture::destroy);
*texture_id = id;
}
/* Return the GL texture ID that was set for this texture */
GLuint Texture::id() const
{
return *texture_id;
}
void Texture::bind() const
{
glBindTexture(GL_TEXTURE_2D, this->id());
@ -129,16 +119,17 @@ glm::vec2 Texture::size() const
}
}
/* Delete this texture, freeing the memory */
void Texture::destroy(GLuint* id)
{
/* not sure why SDL_Log works here but SDL_LogDebug and SDL_LogInfo don't */
SDL_Log("destroying texture ID %i", *id);
glDeleteTextures(1, id);
}
/* Textures are considered equal if they have the same ID */
bool Texture::operator==(const Texture& texture) const
{
return id() == texture.id();
}
/* This function gets passed to the abstract base class for deleting the texture data when the ID
* pointer goes out of scope (when all instances of this texture and its copies are out of scope) */
void texture_deleter(GLuint* id)
{
/* not sure why SDL_Log works here at program end but SDL_LogDebug and SDL_LogInfo don't */
SDL_Log("destroying texture ID %i", *id);
glDeleteTextures(1, id);
}

View File

@ -20,12 +20,12 @@
#ifndef Texture_h_
#define Texture_h_
#include <memory>
#include <stdexcept>
#include "SDL.h"
#include "SDL_image.h"
#include "sdl2-gfx/SDL2_rotozoom.h"
#include "filesystem.hpp"
#include "GLObject.hpp"
#include "Game.hpp"
/* include Open GL */
@ -35,34 +35,32 @@
#include "glew/glew.h"
#endif
class Texture
class Texture : public GLObject
{
private:
fs::path path = "";
std::shared_ptr<GLuint> texture_id = nullptr;
public:
Texture() {};
Texture();
Texture(fs::path);
void associate(fs::path);
void generate() override;
void generate(glm::vec2);
bool generated() const;
void load();
void load(fs::path);
void load(SDL_RWops*);
void load(SDL_Surface*);
void load(void*, GLenum = GL_RGBA, GLenum = GL_UNSIGNED_BYTE);
void load(void*, glm::vec2, GLenum = GL_RGBA, GLenum = GL_UNSIGNED_BYTE);
void id(GLuint);
GLuint id() const;
void bind() const;
void bind() const override;
glm::vec2 size() const;
static void destroy(GLuint*);
bool operator==(const Texture&) const;
};
void texture_deleter(GLuint*);
#endif