This commit is contained in:
79
include/resources/image.hpp
Normal file
79
include/resources/image.hpp
Normal file
@@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
|
||||
#include <glm/vec2.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <filesystem>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace kuiper
|
||||
{
|
||||
|
||||
namespace resource
|
||||
{
|
||||
|
||||
struct image_error {
|
||||
std::string_view message;
|
||||
};
|
||||
|
||||
class image {
|
||||
public:
|
||||
image(std::uint32_t width,
|
||||
std::uint32_t height,
|
||||
std::uint32_t n_channels,
|
||||
const std::uint8_t* data,
|
||||
std::size_t len)
|
||||
: m_width(width), m_height(height), m_channels(n_channels), m_data(data, data + len) {}
|
||||
image() = default;
|
||||
~image() = default;
|
||||
image(const image& other) = default;
|
||||
image& operator=(const image& other) = default;
|
||||
image(image&& other) noexcept = default;
|
||||
image& operator=(image&& other) noexcept = default;
|
||||
|
||||
static image make_blank(std::uint32_t width, std::uint32_t height, std::uint32_t n_channels) noexcept;
|
||||
static std::expected<image, image_error> from_path(const std::filesystem::path& path,
|
||||
std::uint8_t num_channels = 4) noexcept;
|
||||
static std::expected<image, image_error> from_memory(const std::uint8_t* data,
|
||||
std::size_t len,
|
||||
std::uint8_t num_channels = 4) noexcept;
|
||||
|
||||
std::uint32_t width() const noexcept {
|
||||
return m_width;
|
||||
}
|
||||
|
||||
std::uint32_t height() const noexcept {
|
||||
return m_height;
|
||||
}
|
||||
|
||||
glm::uvec2 dimensions() const noexcept {
|
||||
return {m_width, m_height};
|
||||
}
|
||||
|
||||
std::uint32_t channels() const noexcept {
|
||||
return m_channels;
|
||||
}
|
||||
|
||||
const std::vector<std::uint8_t>& pixel_data() const noexcept {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t>& pixel_data_mut() noexcept {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
void resize(std::uint32_t width, std::uint32_t height) noexcept;
|
||||
|
||||
private:
|
||||
std::uint32_t m_width {0};
|
||||
std::uint32_t m_height {0};
|
||||
std::uint32_t m_channels {0};
|
||||
std::vector<std::uint8_t> m_data {};
|
||||
};
|
||||
|
||||
} // namespace resource
|
||||
|
||||
} // namespace kuiper
|
||||
20
include/resources/material.hpp
Normal file
20
include/resources/material.hpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "graphics/opengl/texture.hpp"
|
||||
#include "graphics/opengl/texture_array.hpp"
|
||||
|
||||
#include <glm/vec4.hpp>
|
||||
|
||||
namespace kuiper::resource
|
||||
{
|
||||
|
||||
struct material {
|
||||
glm::vec4 base_colour_factor {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
float metallic_factor {1.0f};
|
||||
float roughness_factor {1.0f};
|
||||
|
||||
// 0: Albedo, 1: Normal, 2: Metallic-Roughness
|
||||
gl::texture_array::s_ptr textures {nullptr};
|
||||
};
|
||||
|
||||
} // namespace kuiper::resource
|
||||
55
include/resources/mesh.hpp
Normal file
55
include/resources/mesh.hpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#include "maths/transform.hpp"
|
||||
#include "resources/primitive.hpp"
|
||||
|
||||
#include <glm/mat4x4.hpp>
|
||||
|
||||
#include <initializer_list>
|
||||
#include <vector>
|
||||
|
||||
namespace kuiper::resource
|
||||
{
|
||||
|
||||
class mesh {
|
||||
public:
|
||||
using primitive_storage = std::vector<primitive>;
|
||||
using submesh_storage = std::vector<mesh>;
|
||||
|
||||
mesh(const glm::mat4& t)
|
||||
: m_transform(t) {}
|
||||
|
||||
mesh(const glm::mat4& t, std::initializer_list<primitive> primitives)
|
||||
: m_transform(t) {
|
||||
for (const auto& p : primitives) {
|
||||
m_primitives.push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
void add_primitive(const primitive& prim) {
|
||||
return m_primitives.push_back(prim);
|
||||
}
|
||||
|
||||
void add_submesh(const class mesh& mesh) {
|
||||
return m_submeshes.push_back(mesh);
|
||||
}
|
||||
|
||||
const glm::mat4& transform() const noexcept {
|
||||
return m_transform;
|
||||
}
|
||||
|
||||
const primitive_storage& primitives() const noexcept {
|
||||
return m_primitives;
|
||||
}
|
||||
|
||||
const submesh_storage& submeshes() const noexcept {
|
||||
return m_submeshes;
|
||||
}
|
||||
|
||||
private:
|
||||
primitive_storage m_primitives {};
|
||||
submesh_storage m_submeshes {};
|
||||
glm::mat4 m_transform {};
|
||||
};
|
||||
|
||||
} // namespace kuiper::resource
|
||||
56
include/resources/model.hpp
Normal file
56
include/resources/model.hpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include "errors/errors.hpp"
|
||||
#include "resources/material.hpp"
|
||||
#include "resources/mesh.hpp"
|
||||
|
||||
#include <fastgltf/core.hpp>
|
||||
|
||||
#include <expected>
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
|
||||
namespace kuiper::resource
|
||||
{
|
||||
|
||||
class model {
|
||||
public:
|
||||
using mesh_storage = std::vector<mesh>;
|
||||
using material_storage = std::vector<material>;
|
||||
|
||||
model() = default;
|
||||
model(std::initializer_list<mesh> meshes) {
|
||||
for (const auto& m : meshes) {
|
||||
m_meshes.push_back(m);
|
||||
}
|
||||
}
|
||||
|
||||
void push_mesh(const mesh& m) {
|
||||
return m_meshes.push_back(m);
|
||||
}
|
||||
|
||||
void push_material(const material& m) {
|
||||
return m_materials.push_back(m);
|
||||
}
|
||||
|
||||
const mesh_storage& meshes() const noexcept {
|
||||
return m_meshes;
|
||||
}
|
||||
|
||||
const material_storage& materials() const noexcept {
|
||||
return m_materials;
|
||||
}
|
||||
|
||||
/// Construct a `model` from a path to a glTF file
|
||||
static std::expected<model, kuiper::error> from_gltf_path(const std::filesystem::path& gltf_path);
|
||||
/// Construct a `model` from a path to a glTF file, prefer this function to the above as fastgltf's `Parser` should
|
||||
/// ideally be re-used (only on one thread, though)
|
||||
static std::expected<model, kuiper::error> from_gltf_path(const std::filesystem::path& gltf_path,
|
||||
fastgltf::Parser& gltf_parser);
|
||||
|
||||
private:
|
||||
mesh_storage m_meshes;
|
||||
material_storage m_materials;
|
||||
};
|
||||
|
||||
} // namespace kuiper::resource
|
||||
38
include/resources/primitive.hpp
Normal file
38
include/resources/primitive.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <glm/vec2.hpp>
|
||||
#include <glm/vec3.hpp>
|
||||
#include <glm/vec4.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace kuiper
|
||||
{
|
||||
|
||||
struct vertex {
|
||||
glm::vec3 position; // (x, y, z), float
|
||||
glm::vec3 normal; // (x, y, z), float
|
||||
glm::vec4 tangent; // (x, y, z, w), float
|
||||
glm::vec2 uv; // (x, y) float
|
||||
};
|
||||
|
||||
enum class primitive_type : std::uint8_t {
|
||||
none = 0,
|
||||
triangles
|
||||
};
|
||||
|
||||
} // namespace kuiper
|
||||
|
||||
namespace kuiper::resource
|
||||
{
|
||||
|
||||
struct primitive {
|
||||
primitive_type type {primitive_type::none};
|
||||
std::vector<vertex> vertices {};
|
||||
std::vector<std::uint32_t> indices {};
|
||||
std::size_t material_idx {};
|
||||
};
|
||||
|
||||
} // namespace kuiper::resource
|
||||
13
include/resources/resource_index.hpp
Normal file
13
include/resources/resource_index.hpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
namespace kuiper::resource
|
||||
{
|
||||
|
||||
class index {
|
||||
public:
|
||||
static index from_file(const std::filesystem::path& index_path) noexcept;
|
||||
};
|
||||
|
||||
} // namespace kuiper::resource
|
||||
96
include/resources/resource_manager.hpp
Normal file
96
include/resources/resource_manager.hpp
Normal file
@@ -0,0 +1,96 @@
|
||||
#pragma once
|
||||
|
||||
#include "graphics/opengl/shader.hpp"
|
||||
#include "graphics/opengl/texture.hpp"
|
||||
#include "resources/material.hpp"
|
||||
#include "resources/model.hpp"
|
||||
#include "utils/xoshiro256plusplus.hpp"
|
||||
|
||||
#include <absl/container/flat_hash_map.h>
|
||||
|
||||
#include <concepts>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
namespace kuiper
|
||||
{
|
||||
|
||||
using resource_id_t = std::uint32_t;
|
||||
|
||||
enum class resource_type : std::uint8_t {
|
||||
none = 0,
|
||||
texture,
|
||||
shader,
|
||||
model
|
||||
};
|
||||
|
||||
struct resource_metadata {
|
||||
resource_id_t id {0};
|
||||
resource_type type {resource_type::none};
|
||||
std::string name {};
|
||||
};
|
||||
|
||||
class resource_manager {
|
||||
public:
|
||||
using metadata_map_t = absl::flat_hash_map<resource_id_t, resource_metadata>;
|
||||
using texture_map_t = absl::flat_hash_map<resource_id_t, gl::texture::s_ptr>;
|
||||
using shader_map_t = absl::flat_hash_map<resource_id_t, gl::shader::s_ptr>;
|
||||
using model_map_t = absl::flat_hash_map<resource_id_t, resource::model>;
|
||||
using material_map_t = absl::flat_hash_map<resource_id_t, resource::material>;
|
||||
|
||||
template<typename T>
|
||||
resource_metadata add(T&& resource, std::string_view name = {}) {
|
||||
const auto new_id = static_cast<resource_id_t>(m_prng.next());
|
||||
resource_type type = resource_type::none;
|
||||
|
||||
if constexpr (std::same_as<T, resource::model>) {
|
||||
type = resource_type::model;
|
||||
m_models.insert({new_id, std::forward<T>(resource)});
|
||||
} else {
|
||||
static_assert(!"non-exhaustive if constexpr");
|
||||
}
|
||||
|
||||
resource_metadata metadata {new_id, type, std::string(name)};
|
||||
m_metadata.insert({new_id, metadata});
|
||||
return metadata;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::optional<T> get(resource_id_t id) {
|
||||
if constexpr (std::same_as<T, resource::model>) {
|
||||
if (m_models.contains(id)) {
|
||||
return m_models.at(id);
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
} else {
|
||||
static_assert(!"non-exhaustive if constexpr");
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<resource_metadata> import_from_path(const std::filesystem::path& path);
|
||||
|
||||
const metadata_map_t& metadata() const noexcept {
|
||||
return m_metadata;
|
||||
}
|
||||
|
||||
const model_map_t& models() const noexcept {
|
||||
return m_models;
|
||||
}
|
||||
|
||||
private:
|
||||
random::xoshiro256pp m_prng {random::xoshiro256pp::from_random_device()};
|
||||
|
||||
metadata_map_t m_metadata {};
|
||||
texture_map_t m_textures {};
|
||||
shader_map_t m_shaders {};
|
||||
model_map_t m_models {};
|
||||
material_map_t m_materials {};
|
||||
};
|
||||
|
||||
} // namespace kuiper
|
||||
Reference in New Issue
Block a user