spacebox/src/Model.hpp

177 lines
6.2 KiB
C++

/* +------------------------------------------------------+
____/ \____ /| - Open source game framework licensed to freely use, |
\ / / | copy, modify and sell without restriction |
+--\ ^__^ /--+ | |
| ~/ \~ | | - created for <https://foam.shampoo.ooo> |
| ~~~~~~~~~~~~ | +------------------------------------------------------+
| SPACE ~~~~~ | /
| ~~~~~~~ BOX |/
+-------------*/
#pragma once
/* GL functions */
#if defined(__EMSCRIPTEN__)
#include <GL/glew.h>
#elif defined(__ANDROID__) || defined(ANDROID)
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
#else
#include "glew/glew.h"
#endif
#include <iostream>
#include <string>
#include <map>
#include <memory>
#include <iterator>
#include <stdexcept>
#include "glm/glm.hpp"
#include "Attributes.hpp"
#include "Texture.hpp"
#include "Carousel.hpp"
namespace sb
{
class Model
{
private:
inline static const std::string DEFAULT_TEXTURE_NAME = "default";
std::map<std::string, sb::Texture> _textures;
std::map<std::string, std::shared_ptr<sb::Attributes>> _attributes;
glm::mat4 _transformation {1.0f};
public:
Model();
Model(const std::map<std::string, std::shared_ptr<sb::Attributes>>&);
Model(const std::map<std::string, sb::Attributes>&);
Model(const std::initializer_list<std::string>&);
std::map<std::string, std::shared_ptr<sb::Attributes>>& attributes();
std::shared_ptr<sb::Attributes>& attributes(const std::string&);
void attributes(const sb::Attributes&, const std::string&);
void attributes(const std::shared_ptr<sb::Attributes>&, const std::string&);
std::shared_ptr<sb::Attributes>& operator[](const std::string&);
void enable();
void disable();
std::map<std::string, sb::Texture>& textures();
sb::Texture& texture(const std::string&);
sb::Texture& texture();
void texture(const sb::Texture&, const std::string&);
void texture(const sb::Texture&);
/*!
* @return a constanst reference to the model's transformation matrix
*/
const glm::mat4& transformation() const;
/*!
* Apply the given transformation matrix to the model's current transformation matrix.
*
* @return the model's new transformation matrix
*/
const glm::mat4& transform(const glm::mat4& transformation);
/*!
* Resets the model's transformation to the identity matrix.
*
* @return the model's new transformation matrix, the identity matrix
*/
const glm::mat4& untransform();
/*!
* Specialized version of transform(const glm::mat4&) that builds a scale transformation from an x, y, z vector and
* applies it to the model's transformation matrix.
*
* @param scale x, y, z scale
* @return the model's new transformation matrix
*/
const glm::mat4& scale(const glm::vec3& scale);
/*!
* Scale all dimensions by the same amount.
* @overload scale(const glm::vec3&)
*/
const glm::mat4& scale(float scale);
/*!
* Specialized version of transform(const glm::mat4&) that builds a rotation matrix from an angle in radians and an axis
* vector and applies it to the model's transformation matrix.
*
* The axis is the vector around which the model will be rotated. For example, to rotate a 2D plane around the origin, use
* the z-axis: `glm::vec3(0.0f, 0.0f, 1.0f)`.
*
* @param angle angle in radians
* @param axis axis to rotate the model around
* @return the model's new transformation matrix
*/
const glm::mat4& rotate(float angle, glm::vec3 axis);
/*!
* Specialized version of transform(const glm::mat4&) that builds a translation matrix from a 3D translation vector
* indicating the distance to translate along each axis and applies it to the model's transformation matrix.
*
* @param translation distance to translate in the x, y, and z dimensions
* @return the model's new transformation matrix
*/
const glm::mat4& translate(glm::vec3 translation);
std::size_t size();
operator glm::mat4() const;
};
class Plane : public Model
{
public:
/* A plane in the X and Y dimensions, from (-1.0, -1.0) to (1.0, 1.0) */
inline const static std::shared_ptr<sb::Attributes> position = std::make_shared<sb::Attributes>(sb::Attributes{
{-1.0f, 1.0f}, {1.0f, 1.0f}, {-1.0f, -1.0f},
{1.0f, 1.0f}, {1.0f, -1.0f}, {-1.0f, -1.0f}
});
/* Map a texture to fill the plane */
inline const static std::shared_ptr<sb::Attributes> uv = std::make_shared<sb::Attributes>(sb::Attributes{
{0.0f, 1.0f}, {1.0f, 1.0f}, {0.0f, 0.0f},
{1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 0.0f}
});
/* A gradient from magenta to yellow */
inline const static std::shared_ptr<sb::Attributes> color = std::make_shared<sb::Attributes>(sb::Attributes{
{1.0f, 1.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 0.0f, 1.0f}, {0.8f, 0.0f, 0.3f, 1.0f},
{1.0f, 1.0f, 0.0f, 1.0f}, {0.8f, 0.0f, 0.3f, 1.0f}, {0.8f, 0.0f, 0.3f, 1.0f}
});
Plane() : Model(std::map<std::string, std::shared_ptr<sb::Attributes>>({{"position", position}, {"uv", uv}, {"color", color}})) {}
};
/*!
* A version of `Plane` which contains two texture objects, one of which is active at a time. A reference
* to the active `sb::Texture` object is available from `PlaneDoubleBuffer.active`, and the inactive object is
* available from `PlaneDoubleBuffer.inactive`. The buffers can be swapped using `PlaneDoubleBuffer.swap`.
*/
class PlaneDoubleBuffer : public Plane
{
private:
bool swapped = false;
public:
PlaneDoubleBuffer();
void generate(const glm::vec2&);
sb::Texture& active();
sb::Texture& inactive();
void swap();
};
}