296 lines
6.7 KiB
C++
296 lines
6.7 KiB
C++
/* +------------------------------------------------------+
|
|
____/ \____ /| - Open source game framework licensed to freely use, |
|
|
\ / / | copy, modify and sell without restriction |
|
|
+--\ ^__^ /--+ | |
|
|
| ~/ \~ | | - created for <https://foam.shampoo.ooo> |
|
|
| ~~~~~~~~~~~~ | +------------------------------------------------------+
|
|
| SPACE ~~~~~ | /
|
|
| ~~~~~~~ BOX |/
|
|
+-------------*/
|
|
|
|
#include "Model.hpp"
|
|
|
|
sb::Model::Model(const std::map<std::string, std::shared_ptr<sb::Attributes>>& attributes_pack)
|
|
{
|
|
for (auto attributes : attributes_pack)
|
|
{
|
|
this->attributes(attributes.second, attributes.first);
|
|
}
|
|
}
|
|
|
|
sb::Model::Model(const std::map<std::string, sb::Attributes>& attributes_pack)
|
|
{
|
|
for (auto attributes : attributes_pack)
|
|
{
|
|
this->attributes(attributes.second, attributes.first);
|
|
}
|
|
}
|
|
|
|
sb::Model::Model(const std::initializer_list<std::string>& names)
|
|
{
|
|
for (const std::string& name : names)
|
|
{
|
|
this->attributes(sb::Attributes(), name);
|
|
}
|
|
}
|
|
|
|
std::map<std::string, std::shared_ptr<sb::Attributes>>& sb::Model::attributes()
|
|
{
|
|
return _attributes;
|
|
}
|
|
|
|
const std::map<std::string, std::shared_ptr<sb::Attributes>>& sb::Model::attributes() const
|
|
{
|
|
return _attributes;
|
|
}
|
|
|
|
std::shared_ptr<sb::Attributes>& sb::Model::attributes(const std::string& name)
|
|
{
|
|
return attributes().at(name);
|
|
}
|
|
|
|
const std::shared_ptr<sb::Attributes>& sb::Model::attributes(const std::string& name) const
|
|
{
|
|
return attributes().at(name);
|
|
}
|
|
void sb::Model::attributes(const sb::Attributes& attributes, const std::string& name)
|
|
{
|
|
this->attributes(std::make_shared<sb::Attributes>(attributes), name);
|
|
}
|
|
|
|
void sb::Model::attributes(const std::shared_ptr<sb::Attributes>& attributes, const std::string& name)
|
|
{
|
|
this->attributes()[name] = attributes;
|
|
}
|
|
|
|
std::shared_ptr<sb::Attributes>& sb::Model::operator[](const std::string& name)
|
|
{
|
|
auto element = attributes().find(name);
|
|
/* add an empty Attributes at name if it doesn't exist yet */
|
|
if (element == attributes().end())
|
|
{
|
|
attributes(sb::Attributes{}, name);
|
|
}
|
|
return attributes()[name];
|
|
}
|
|
|
|
void sb::Model::enable() const
|
|
{
|
|
for (const auto& attributes : this->attributes())
|
|
{
|
|
try
|
|
{
|
|
attributes.second->enable();
|
|
}
|
|
catch (const std::runtime_error& error)
|
|
{
|
|
std::ostringstream message;
|
|
message << "Error enabling " << attributes.first << " attributes on model: " << error.what();
|
|
throw std::runtime_error(message.str());
|
|
}
|
|
}
|
|
}
|
|
|
|
void sb::Model::disable() const
|
|
{
|
|
for (const auto& attributes : this->attributes())
|
|
{
|
|
attributes.second->disable();
|
|
}
|
|
}
|
|
|
|
const std::vector<sb::Texture>& sb::Model::textures() const
|
|
{
|
|
return _textures;
|
|
}
|
|
|
|
std::vector<sb::Texture>& sb::Model::textures()
|
|
{
|
|
return _textures;
|
|
}
|
|
|
|
const sb::Texture& sb::Model::texture(int index) const
|
|
{
|
|
if (textures().empty())
|
|
{
|
|
throw std::out_of_range("There are no textures attached to this model.");
|
|
}
|
|
else
|
|
{
|
|
return textures()[glm::mod(index, static_cast<int>(textures().size()))];
|
|
}
|
|
}
|
|
|
|
sb::Texture& sb::Model::texture(int index)
|
|
{
|
|
if (textures().empty())
|
|
{
|
|
throw std::out_of_range("There are no textures attached to this model.");
|
|
}
|
|
else
|
|
{
|
|
return textures()[glm::mod(index, static_cast<int>(textures().size()))];
|
|
}
|
|
}
|
|
|
|
void sb::Model::texture(const sb::Texture& texture)
|
|
{
|
|
textures().push_back(texture);
|
|
}
|
|
|
|
void sb::Model::load()
|
|
{
|
|
for (sb::Texture& texture : textures())
|
|
{
|
|
texture.load();
|
|
}
|
|
}
|
|
|
|
void sb::Model::add(sb::VBO& vbo)
|
|
{
|
|
for (auto& [name, attributes] : attributes())
|
|
{
|
|
vbo.add(*attributes);
|
|
}
|
|
}
|
|
|
|
void sb::Model::bind_textures() const
|
|
{
|
|
for (const sb::Texture& texture : textures())
|
|
{
|
|
try
|
|
{
|
|
texture.bind();
|
|
}
|
|
catch (const std::runtime_error& error)
|
|
{
|
|
std::ostringstream message;
|
|
message << "Error binding " << *this << ": " << error.what();
|
|
throw std::runtime_error(message.str());
|
|
}
|
|
}
|
|
}
|
|
|
|
void sb::Model::bind_attributes() const
|
|
{
|
|
for (auto& [name, attributes] : attributes())
|
|
{
|
|
try
|
|
{
|
|
attributes->bind();
|
|
}
|
|
catch (const std::runtime_error& error)
|
|
{
|
|
std::ostringstream message;
|
|
message << "Error binding " << *this << ": " << error.what();
|
|
throw std::runtime_error(message.str());
|
|
}
|
|
}
|
|
}
|
|
|
|
void sb::Model::bind() const
|
|
{
|
|
bind_textures();
|
|
bind_attributes();
|
|
}
|
|
|
|
const glm::mat4& sb::Model::transformation() const
|
|
{
|
|
return _transformation;
|
|
}
|
|
|
|
const glm::mat4& sb::Model::transform(const glm::mat4& transformation)
|
|
{
|
|
_transformation *= transformation;
|
|
return this->transformation();
|
|
}
|
|
|
|
const glm::mat4& sb::Model::untransform()
|
|
{
|
|
_transformation = glm::mat4(1.0f);
|
|
return transformation();
|
|
}
|
|
|
|
const glm::mat4& sb::Model::scale(const glm::vec3& scale)
|
|
{
|
|
return transform(glm::scale(scale));
|
|
}
|
|
|
|
const glm::mat4& sb::Model::rotate(float angle, glm::vec3 axis)
|
|
{
|
|
return transform(glm::rotate(angle, axis));
|
|
}
|
|
|
|
const glm::mat4& sb::Model::translate(glm::vec3 translation)
|
|
{
|
|
return transform(glm::translate(translation));
|
|
}
|
|
|
|
|
|
std::size_t sb::Model::size() const
|
|
{
|
|
std::size_t sum = 0;
|
|
for (const auto& attributes : this->attributes())
|
|
{
|
|
sum += attributes.second->size();
|
|
}
|
|
return sum;
|
|
}
|
|
|
|
sb::Model::operator glm::mat4() const
|
|
{
|
|
return _transformation;
|
|
}
|
|
|
|
sb::Model::operator std::string() const
|
|
{
|
|
std::ostringstream message;
|
|
message << "<sb::Model with " << _textures.size() << " textures";
|
|
if (_attributes.size() > 0)
|
|
{
|
|
message << " and " << _attributes.size() << " attributes ( ";
|
|
for (const auto& [name, attributes] : _attributes)
|
|
{
|
|
message << name << " ";
|
|
}
|
|
message << ")";
|
|
}
|
|
message << ">";
|
|
return message.str();
|
|
}
|
|
|
|
std::ostream& sb::operator<<(std::ostream& out, const sb::Model& model)
|
|
{
|
|
out << std::string(model);
|
|
return out;
|
|
}
|
|
|
|
sb::PlaneDoubleBuffer::PlaneDoubleBuffer() : Plane()
|
|
{
|
|
texture(sb::Texture());
|
|
texture(sb::Texture());
|
|
}
|
|
|
|
void sb::PlaneDoubleBuffer::generate(const glm::vec2& size)
|
|
{
|
|
for (sb::Texture* buffer : {&texture(FRONT), &texture(BACK)})
|
|
{
|
|
buffer->generate(size);
|
|
}
|
|
}
|
|
|
|
sb::Texture& sb::PlaneDoubleBuffer::active()
|
|
{
|
|
return swapped ? texture(BACK) : texture(FRONT);
|
|
}
|
|
|
|
sb::Texture& sb::PlaneDoubleBuffer::inactive()
|
|
{
|
|
return swapped ? texture(FRONT) : texture(BACK);
|
|
}
|
|
|
|
void sb::PlaneDoubleBuffer::swap()
|
|
{
|
|
swapped = !swapped;
|
|
}
|