diff --git a/.clang-tidy b/.clang-tidy
new file mode 100755
index 0000000..de3935e
--- /dev/null
+++ b/.clang-tidy
@@ -0,0 +1,148 @@
+# Generated from CLion Inspection settings
+---
+Checks: '-*,
+bugprone-argument-comment,
+bugprone-assert-side-effect,
+bugprone-bad-signal-to-kill-thread,
+bugprone-branch-clone,
+bugprone-copy-constructor-init,
+bugprone-dangling-handle,
+bugprone-dynamic-static-initializers,
+bugprone-fold-init-type,
+bugprone-forward-declaration-namespace,
+bugprone-forwarding-reference-overload,
+bugprone-inaccurate-erase,
+bugprone-incorrect-roundings,
+bugprone-integer-division,
+bugprone-lambda-function-name,
+bugprone-macro-parentheses,
+bugprone-macro-repeated-side-effects,
+bugprone-misplaced-operator-in-strlen-in-alloc,
+bugprone-misplaced-pointer-arithmetic-in-alloc,
+bugprone-misplaced-widening-cast,
+bugprone-move-forwarding-reference,
+bugprone-multiple-statement-macro,
+bugprone-no-escape,
+bugprone-not-null-terminated-result,
+bugprone-parent-virtual-call,
+bugprone-posix-return,
+bugprone-reserved-identifier,
+bugprone-sizeof-container,
+bugprone-sizeof-expression,
+bugprone-spuriously-wake-up-functions,
+bugprone-string-constructor,
+bugprone-string-integer-assignment,
+bugprone-string-literal-with-embedded-nul,
+bugprone-suspicious-enum-usage,
+bugprone-suspicious-include,
+bugprone-suspicious-memset-usage,
+bugprone-suspicious-missing-comma,
+bugprone-suspicious-semicolon,
+bugprone-suspicious-string-compare,
+bugprone-suspicious-memory-comparison,
+bugprone-suspicious-realloc-usage,
+bugprone-swapped-arguments,
+bugprone-terminating-continue,
+bugprone-throw-keyword-missing,
+bugprone-too-small-loop-variable,
+bugprone-undefined-memory-manipulation,
+bugprone-undelegated-constructor,
+bugprone-unhandled-self-assignment,
+bugprone-unused-raii,
+bugprone-unused-return-value,
+bugprone-use-after-move,
+bugprone-virtual-near-miss,
+cert-dcl21-cpp,
+cert-dcl58-cpp,
+cert-err34-c,
+cert-err52-cpp,
+cert-err60-cpp,
+cert-flp30-c,
+cert-msc50-cpp,
+cert-msc51-cpp,
+cert-str34-c,
+cppcoreguidelines-interfaces-global-init,
+cppcoreguidelines-narrowing-conversions,
+cppcoreguidelines-pro-type-member-init,
+cppcoreguidelines-pro-type-static-cast-downcast,
+cppcoreguidelines-slicing,
+google-default-arguments,
+google-explicit-constructor,
+google-runtime-operator,
+hicpp-exception-baseclass,
+hicpp-multiway-paths-covered,
+misc-misplaced-const,
+misc-new-delete-overloads,
+misc-no-recursion,
+misc-non-copyable-objects,
+misc-throw-by-value-catch-by-reference,
+misc-unconventional-assign-operator,
+misc-uniqueptr-reset-release,
+modernize-avoid-bind,
+modernize-concat-nested-namespaces,
+modernize-deprecated-headers,
+modernize-deprecated-ios-base-aliases,
+modernize-loop-convert,
+modernize-make-shared,
+modernize-make-unique,
+modernize-pass-by-value,
+modernize-raw-string-literal,
+modernize-redundant-void-arg,
+modernize-replace-auto-ptr,
+modernize-replace-disallow-copy-and-assign-macro,
+modernize-replace-random-shuffle,
+modernize-return-braced-init-list,
+modernize-shrink-to-fit,
+modernize-unary-static-assert,
+modernize-use-auto,
+modernize-use-bool-literals,
+modernize-use-emplace,
+modernize-use-equals-default,
+modernize-use-equals-delete,
+modernize-use-nodiscard,
+modernize-use-noexcept,
+modernize-use-nullptr,
+modernize-use-override,
+modernize-use-transparent-functors,
+modernize-use-uncaught-exceptions,
+mpi-buffer-deref,
+mpi-type-mismatch,
+openmp-use-default-none,
+performance-faster-string-find,
+performance-for-range-copy,
+performance-implicit-conversion-in-loop,
+performance-inefficient-algorithm,
+performance-inefficient-string-concatenation,
+performance-inefficient-vector-operation,
+performance-move-const-arg,
+performance-move-constructor-init,
+performance-no-automatic-move,
+performance-noexcept-move-constructor,
+performance-trivially-destructible,
+performance-type-promotion-in-math-fn,
+performance-unnecessary-copy-initialization,
+performance-unnecessary-value-param,
+portability-simd-intrinsics,
+readability-avoid-const-params-in-decls,
+readability-const-return-type,
+readability-container-size-empty,
+readability-convert-member-functions-to-static,
+readability-delete-null-pointer,
+readability-deleted-default,
+readability-inconsistent-declaration-parameter-name,
+readability-make-member-function-const,
+readability-misleading-indentation,
+readability-misplaced-array-index,
+readability-non-const-parameter,
+readability-redundant-control-flow,
+readability-redundant-declaration,
+readability-redundant-function-ptr-dereference,
+readability-redundant-smartptr-get,
+readability-redundant-string-cstr,
+readability-redundant-string-init,
+readability-simplify-subscript-expr,
+readability-static-accessed-through-handle,
+readability-static-definition-in-anonymous-namespace,
+readability-string-compare,
+readability-uniqueptr-delete-release,
+readability-use-anyofallof'
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100755
index 0000000..2dff2f0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+cmake-build-debug
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100755
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..77ce906
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,158 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100755
index 0000000..79ee123
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100755
index 0000000..0310f9d
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..206a77e
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/point_cloud_viewer.iml b/.idea/point_cloud_viewer.iml
new file mode 100644
index 0000000..f08604b
--- /dev/null
+++ b/.idea/point_cloud_viewer.iml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100755
index 0000000..f74a0f8
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100755
index 0000000..46d0684
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,196 @@
+cmake_minimum_required(VERSION 3.27)
+project(z3d)
+
+set(CMAKE_CXX_STANDARD 23)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Ofast -pedantic -Wall -Werror ")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fmacro-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}/=")
+
+add_executable(z3d main.cpp
+ include/assets/components/material_components.hpp
+ include/assets/components/point_cloud_vertex_components.hpp
+ include/assets/components/mesh_vertex_components.hpp
+ include/assets/dynamic_read_buffers/dynamic_material_buffer.hpp
+ include/assets/dynamic_read_buffers/dynamic_mesh_buffer.hpp
+ include/assets/dynamic_read_buffers/dynamic_point_cloud_buffer.hpp
+ include/assets/data_loaders/kitti_loader.hpp
+ include/assets/data_loaders/obj_loader.hpp
+ include/assets/data_loaders/stl_loader.hpp
+ include/assets/data_loaders/uos_loader.hpp
+ include/assets/components/mesh_vertex_components.hpp
+ include/scene/camera.hpp
+ include/scene/flying_camera.hpp
+ include/opengl/handles/mesh_handle.hpp
+ include/opengl/handles/point_cloud_handle.hpp
+ include/opengl/handles/shader_program_handle.hpp
+ include/opengl/handles/texture_handle.hpp
+ include/opengl/data/mesh_data.hpp
+ include/opengl/data/point_cloud_data.hpp
+ include/opengl/data/shader_program_data.hpp
+ include/opengl/data/texture_data.hpp
+ include/scene/lighting_setup.hpp
+ include/rendering/batch_renderers/mesh_batch_renderer.hpp
+ include/opengl/error.hpp
+ include/rendering/batches/mesh_batch.hpp
+ include/rendering/batches/point_cloud_batch.hpp
+ include/util/arx.hpp
+ include/util/extra_arx_parsers.hpp
+ include/util/for_each.hpp
+ include/util/function.hpp
+ include/util/image.hpp
+ include/util/logger.hpp
+ include/util/string_indexer.hpp
+ include/util/string_literal.hpp
+ include/util/uix.hpp
+ source/assets/data_loaders/stl_loader.cpp
+ source/assets/data_loaders/obj_loader.cpp
+ source/scene/flying_camera.cpp
+ source/opengl/data/point_cloud_data.cpp
+ source/opengl/handles/shader_program_handle.ipp
+ source/opengl/data/texture_data.ipp
+ source/opengl/data/mesh_data.cpp
+ include/opengl/error.hpp
+ source/opengl/data/shader_program_data.cpp
+ source/opengl/handles/mesh_handle.ipp
+ source/opengl/handles/point_cloud_handle.ipp
+ source/opengl/handles/texture_handle.ipp
+ include/assets/data/surface_properties.hpp
+ include/util/unroll_bool_template.hpp
+ include/rendering/batch_renderers/point_cloud_batch_renderer.hpp
+ source/rendering/batches/mesh_batch.ipp
+ source/rendering/batches/point_cloud_batch.ipp
+ include/opengl/shader_program_variable.hpp
+ include/opengl/type_utils.hpp
+ include/util/binary_ifstream.hpp
+ source/assets/data_loaders/kitti_loader.cpp
+ include/assets/data_loaders/generic/generic_3dtk_loader.hpp
+ include/assets/data_loaders/uosr_loader.hpp
+ include/assets/data_loaders/uos_normal_loader.hpp
+ include/assets/data_loaders/uos_rgb_loader.hpp
+ include/assets/dynamic_data_loaders/dynamic_mesh_loader.hpp
+ source/assets/dynamic_data_loaders/dynamic_mesh_loader.cpp
+ source/assets/dynamic_data_loaders/dynamic_mesh_loader.cpp
+ include/assets/dynamic_data_loaders/dynamic_point_cloud_loader.hpp
+ include/assets/dynamic_data_loaders/generic/base_dynamic_loader.hpp
+ source/assets/dynamic_data_loaders/generic/base_dynamic_loader.ipp
+ source/assets/dynamic_data_loaders/dynamic_point_cloud_loader.cpp
+ include/opengl/handles/matrix_handles.hpp
+ include/viewer/instance.hpp
+ include/opengl/data/material_data.hpp
+ include/opengl/handles/material_handle.hpp
+ include/opengl/handles/surface_properties_handle.hpp
+ include/opengl/handles/alpha_handle.hpp
+ source/opengl/data/material_data.ipp
+ include/util/specialised_lambda.hpp
+ include/viewer/asset_types.hpp
+ source/viewer/instance.cpp
+ include/viewer/asset_loader.hpp
+ source/viewer/asset_loader.cpp
+ include/assets/data_loaders/glsl_loader.hpp
+ include/assets/dynamic_read_buffers/dynamic_shader_buffer.hpp
+ source/assets/data_loaders/glsl_loader.cpp
+ include/viewer/settings.hpp
+ include/opengl/data/shader_data.hpp
+ source/opengl/data/shader_data.ipp
+ source/opengl/data/point_cloud_data.ipp
+ source/opengl/data/shader_data.cpp
+ include/opengl/handles/shader_handle.hpp
+ include/util/string_lookup.hpp
+ include/viewer/dynamic_shader_program_loading.hpp
+ source/viewer/dynamic_shader_program_loading.cpp
+ source/opengl/handles/shader_program_handle.cpp
+ include/opengl/shader_program_lookup.hpp
+ source/opengl/shader_program_lookup.cpp
+ include/shader_program/attributes/mesh_attributes.hpp
+ include/shader_program/attributes/point_cloud_attributes.hpp
+ include/shader_program/uniforms/mesh_uniforms.hpp
+ include/shader_program/uniforms/point_cloud_uniforms.hpp
+ include/shader_program/capabilities/mesh_capabilities.hpp
+ include/shader_program/capabilities/point_cloud_capabilities.hpp
+ include/rendering/requirements/mesh_requirements.hpp
+ include/rendering/requirements/point_cloud_requirements.hpp
+ include/rendering/modes/mesh_modes.hpp
+ include/rendering/modes/point_cloud_modes.hpp
+ source/rendering/batch_renderers/mesh_batch_renderer.cpp
+ source/rendering/batch_renderers/point_cloud_batch_renderer.cpp
+ include/rendering/shader_program_lookups/mesh_lookup.hpp
+ include/rendering/shader_program_lookups/mesh_lookup.hpp
+ source/rendering/shader_program_lookups/mesh_lookup.cpp
+ source/rendering/shader_program_lookups/point_cloud_lookup.cpp
+ include/rendering/shader_program_lookups/point_cloud_lookup.hpp
+ include/geometry/aabb.hpp
+ source/geometry/normal_estimation.cpp
+ include/geometry/normal_estimation.hpp
+ include/assets/components/texture_components.hpp
+ include/util/enum_operators.hpp
+ include/assets/dynamic_read_buffers/dynamic_texture_buffer.hpp
+ source/assets/dynamic_read_buffers/dynamic_mesh_buffer.ipp
+ source/assets/dynamic_read_buffers/dynamic_material_buffer.ipp
+ include/assets/dynamic_read_buffers/dynamic_vertex_buffer.hpp
+ source/assets/dynamic_read_buffers/dynamic_model_buffer.ipp
+ source/assets/dynamic_read_buffers/dynamic_texture_buffer.ipp
+ source/assets/dynamic_read_buffers/dynamic_point_cloud_buffer.ipp
+ include/assets/data_loaders/mtl_loader.hpp
+ include/assets/dynamic_data_loaders/dynamic_material_loader.hpp
+ include/util/id_type.hpp
+ include/assets/dynamic_data_stores/generic/generic_dynamic_store.hpp
+ source/assets/dynamic_data_stores/generic/generic_dynamic_store.ipp
+ include/assets/dynamic_data_stores/dynamic_material_store.hpp
+ include/assets/dynamic_data_stores/dynamic_mesh_store.hpp
+ include/assets/dynamic_data_stores/dynamic_point_cloud_store.hpp
+ include/util/result.hpp
+ source/assets/data_loaders/mtl_loader.cpp
+ include/util/line_parser.hpp
+ include/assets/dynamic_data_loaders/dynamic_texture_loader.hpp
+ source/assets/dynamic_data_loaders/dynamic_texture_loader.cpp
+ include/assets/dynamic_data_stores/dynamic_texture_store.hpp
+ include/opengl/data_uploaders/texture_data_uploader.hpp
+ include/assets/dynamic_data_stores/dynamic_vertex_store.hpp
+ include/assets/prefetch_lookups/mesh_prefetch_lookup.hpp
+ include/assets/prefetch_lookups/point_cloud_prefetch_lookup.hpp
+ include/assets/prefetch_lookups/material_prefetch_lookup.hpp
+ include/assets/prefetch_lookups/texture_prefetch_lookup.hpp
+ include/assets/prefetch_lookups/pose_prefetch_lookup.hpp
+ include/assets/dynamic_data_stores/dynamic_pose_store.hpp
+ include/assets/data_loaders/kitti_pose_loader.hpp
+ include/assets/data_loaders/threedtk_pose_loader.hpp
+ source/assets/data_loaders/threedtk_pose_loader.cpp
+ include/assets/dynamic_read_buffers/dynamic_pose_buffer.hpp
+ source/assets/data_loaders/kitti_pose_loader.cpp
+ include/assets/prefetch_queue.hpp
+ include/util/string_list.hpp
+ include/assets/dynamic_data_stores/dynamic_material_library_store.hpp
+ include/assets/dynamic_data_stores/generic/generic_dynamic_component_store.hpp
+ source/assets/dynamic_data_stores/generic/generic_dynamic_component_store.ipp
+ source/assets/dynamic_data_stores/dynamic_material_store.cpp
+ include/assets/dynamic_data_stores/generic/generic_dynamic_component_array_store.hpp
+ source/assets/dynamic_data_stores/generic/generic_dynamic_component_array_store.ipp
+ source/assets/dynamic_data_stores/dynamic_mesh_store.cpp
+ include/assets/dynamic_data_stores/generic/generic_dynamic_indexed_component_array_store.hpp
+ source/assets/dynamic_data_stores/dynamic_point_cloud_store.cpp
+ include/assets/dynamic_read_buffers/dynamic_material_library_buffer.hpp
+ include/assets/dynamic_data_loaders/dynamic_material_library_loader.hpp
+ include/assets/prefetch_lookups/material_library_prefetch_lookup.hpp
+ include/assets/prefetch_lookups/shader_prefetch_lookup.hpp
+ include/assets/dynamic_data_stores/dynamic_shader_store.hpp
+ include/assets/data_loaders/generic/generic_3dtk_loader.hpp
+ source/assets/data_loaders/generic/generic_3dtk_loader.ipp
+ include/assets/prefetch_lookup.hpp
+ source/assets/prefetch_lookups/pose_prefetch_lookup.cpp
+ include/assets/dynamic_data_store.hpp
+)
+
+target_include_directories(z3d PRIVATE include)
+target_include_directories(z3d PRIVATE source) # for ipp headers
+target_include_directories(z3d PRIVATE libraries/include/glm)
+target_include_directories(z3d PRIVATE libraries/include/stb)
+
+find_package(GLEW REQUIRED)
+find_package(OpenGL REQUIRED)
+find_package(SFML REQUIRED COMPONENTS graphics system)
+find_package(Eigen3 3.4 REQUIRED NO_MODULE)
+
+include_directories(${SFML_INCLUDE_DIR})
+include_directories(SYSTEM ${eigen_INCLUDE_DIR})
+target_link_libraries(z3d Eigen3::Eigen sfml-graphics sfml-system sfml-window ${OPENGL_LIBRARIES} ${GLEW_LIBRARIES})
diff --git a/data/fonts/JetBrainsMono_Medium.ttf b/data/fonts/JetBrainsMono_Medium.ttf
new file mode 100755
index 0000000..a6ba552
Binary files /dev/null and b/data/fonts/JetBrainsMono_Medium.ttf differ
diff --git a/include/assets/components/material_components.hpp b/include/assets/components/material_components.hpp
new file mode 100644
index 0000000..e66dfbe
--- /dev/null
+++ b/include/assets/components/material_components.hpp
@@ -0,0 +1,59 @@
+#pragma once
+
+#include
+#include "../dynamic_read_buffers"
+#include "assets/data/surface_properties.hpp"
+#include "util/enum_operators.hpp"
+
+namespace components::material
+{
+using surface_properties = ::surface_properties;
+using transparency = float;
+using ambient_color_texture = ::dynamic_texture_data;
+using diffuse_color_texture = ::dynamic_texture_data;
+using specular_color_texture = ::dynamic_texture_data;
+using shininess_texture = ::dynamic_texture_data;
+using alpha_texture = ::dynamic_texture_data;
+using bump_texture = ::dynamic_texture_data;
+
+namespace indices
+{
+using type = std::size_t;
+inline constexpr type surface_properties = 0;
+inline constexpr type transparency = 1;
+inline constexpr type ambient_color_texture = 2;
+inline constexpr type diffuse_color_texture = 3;
+inline constexpr type specular_color_texture = 4;
+inline constexpr type shininess_texture = 5;
+inline constexpr type alpha_texture = 6;
+inline constexpr type bump_texture = 7;
+}
+
+enum class flags : std::uint8_t
+{
+ none = 0,
+ surface_properties = 1 << indices::surface_properties,
+ transparency = 1 << indices::transparency,
+ ambient_filter_texture = 1 << indices::ambient_color_texture,
+ diffuse_filter_texture = 1 << indices::diffuse_color_texture,
+ specular_filter_texture = 1 << indices::specular_color_texture,
+ shininess_texture = 1 << indices::shininess_texture,
+ alpha_texture = 1 << indices::alpha_texture,
+ bump_texture = 1 << indices::bump_texture
+};
+
+using all = std::tuple<
+ surface_properties,
+ transparency,
+ ambient_color_texture,
+ diffuse_color_texture,
+ specular_color_texture,
+ shininess_texture,
+ alpha_texture,
+ bump_texture
+>;
+constexpr inline auto count = std::tuple_size_v;
+
+} // namespace material_component
+
+DEFINE_ENUM_FLAG_OPERATORS(components::material::flags)
diff --git a/include/assets/components/mesh_vertex_components.hpp b/include/assets/components/mesh_vertex_components.hpp
new file mode 100755
index 0000000..ff578b8
--- /dev/null
+++ b/include/assets/components/mesh_vertex_components.hpp
@@ -0,0 +1,39 @@
+#pragma once
+
+#include
+#include
+#include "util/enum_operators.hpp"
+
+namespace components::mesh_vertex {
+
+using position = std::array;
+using normal = std::array;
+using tex_coord = std::array;
+using color = std::array;
+using reflectance = std::array;
+
+namespace indices
+{
+using type = std::size_t;
+inline constexpr type position = 0;
+inline constexpr type normal = 1;
+inline constexpr type tex_coord = 2;
+inline constexpr type color = 3;
+inline constexpr type reflectance = 4;
+}
+
+enum class flags : std::uint8_t {
+ none = 0,
+ position = 1 << indices::position,
+ normal = 1 << indices::normal,
+ tex_coord = 1 << indices::tex_coord,
+ color = 1 << indices::color,
+ reflectance = 1 << indices::reflectance
+};
+
+using all = std::tuple;
+constexpr inline auto count = std::tuple_size_v;
+
+} // namespace components::mesh_vertex
+
+DEFINE_ENUM_FLAG_OPERATORS(components::mesh_vertex::flags)
diff --git a/include/assets/components/point_cloud_vertex_components.hpp b/include/assets/components/point_cloud_vertex_components.hpp
new file mode 100755
index 0000000..98e3ca1
--- /dev/null
+++ b/include/assets/components/point_cloud_vertex_components.hpp
@@ -0,0 +1,36 @@
+#pragma once
+
+#include
+#include
+#include "util/enum_operators.hpp"
+
+namespace components::point_cloud_vertex {
+
+using position = std::array;
+using normal = std::array;
+using color = std::array;
+using reflectance = std::array;
+
+namespace indices
+{
+using type = std::size_t;
+inline constexpr type position = 0;
+inline constexpr type normal = 1;
+inline constexpr type color = 2;
+inline constexpr type reflectance = 3;
+} // namespace indices
+
+enum class flags : std::uint8_t {
+ none = 0,
+ position = 1 << indices::position,
+ normal = 1 << indices::normal,
+ color = 1 << indices::color,
+ reflectance = 1 << indices::reflectance
+};
+
+using all = std::tuple;
+constexpr inline auto count = std::tuple_size_v;
+
+} // namespace components::point_cloud_vertex
+
+DEFINE_ENUM_FLAG_OPERATORS(components::point_cloud_vertex::flags)
diff --git a/include/assets/components/texture_components.hpp b/include/assets/components/texture_components.hpp
new file mode 100644
index 0000000..f560d31
--- /dev/null
+++ b/include/assets/components/texture_components.hpp
@@ -0,0 +1,28 @@
+#pragma once
+
+#include
+#include
+#include "util/enum_operators.hpp"
+
+namespace components::texture {
+
+using red = std::uint8_t;
+using green = std::uint8_t;
+using blue = std::uint8_t;
+using luminance = std::uint8_t;
+
+enum class flags : std::uint8_t {
+ none = 0,
+ luminance = 1 << 1,
+ red = 1 << 2,
+ green = 1 << 3,
+ blue = 1 << 4,
+ alpha = 1 << 5
+};
+
+using all = std::tuple;
+constexpr inline auto count = std::tuple_size_v;
+
+} // namespace components::texture
+
+DEFINE_ENUM_FLAG_OPERATORS(components::texture::flags)
\ No newline at end of file
diff --git a/include/assets/data/surface_properties.hpp b/include/assets/data/surface_properties.hpp
new file mode 100644
index 0000000..dce0c1e
--- /dev/null
+++ b/include/assets/data/surface_properties.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+#include
+
+struct surface_properties
+{
+ std::array ambient_filter{ 0.7f, 0.7f, 0.7f };
+ std::array diffuse_filter{ 0.466f, 0.466f, 0.7922f };
+ std::array specular_filter{ 0.5974f, 0.2084f, 0.2084f };
+ float shininess{ 100.2237f };
+};
\ No newline at end of file
diff --git a/include/assets/data_loaders/glsl_loader.hpp b/include/assets/data_loaders/glsl_loader.hpp
new file mode 100644
index 0000000..d585c09
--- /dev/null
+++ b/include/assets/data_loaders/glsl_loader.hpp
@@ -0,0 +1,30 @@
+#pragma once
+
+#include
+#include
+#include
+
+#include "assets/dynamic_data_store.hpp"
+#include "assets/prefetch_lookup.hpp"
+#include "assets/prefetch_queue.hpp"
+#include "assets/prefetch_lookups/mesh_prefetch_lookup.hpp"
+#include "assets/dynamic_read_buffers/dynamic_shader_buffer.hpp"
+#include "util/string_list.hpp"
+
+struct glsl_loader
+{
+ static constexpr auto name = std::string_view("glsl");
+
+ [[nodiscard]] static std::error_code prefetch(
+ const file_dir_list& paths,
+ prefetch_queue& queue
+ );
+
+ [[nodiscard]] static std::error_code load(
+ dynamic_shader_buffer& buffer,
+ const file_dir_list& paths,
+ prefetch_lookup& id_lookup,
+ dynamic_data_store& store,
+ bool pedantic = false
+ );
+};
\ No newline at end of file
diff --git a/include/assets/data_loaders/kitti_loader.hpp b/include/assets/data_loaders/kitti_loader.hpp
new file mode 100644
index 0000000..3948380
--- /dev/null
+++ b/include/assets/data_loaders/kitti_loader.hpp
@@ -0,0 +1,53 @@
+#pragma once
+
+#include
+#include
+#include
+
+#include "assets/dynamic_data_store.hpp"
+#include "assets/components/point_cloud_vertex_components.hpp"
+#include "assets/dynamic_read_buffers/dynamic_point_cloud_buffer.hpp"
+#include "assets/dynamic_data_stores/dynamic_point_cloud_store.hpp"
+#include "assets/prefetch_lookup.hpp"
+#include "assets/prefetch_queue.hpp"
+#include "glm/mat4x4.hpp"
+#include "util/result.hpp"
+
+struct kitti_loader
+{
+ static constexpr auto name = std::string_view("kitti");
+
+ [[nodiscard]] static std::error_code prefetch(
+ const file_dir_list& paths,
+ prefetch_queue& queue
+ );
+
+ [[nodiscard]] static std::error_code load(
+ dynamic_point_cloud_buffer& buffer,
+ const file_dir_list& paths,
+ prefetch_lookup& id_lookup,
+ dynamic_data_store& store,
+ bool pedantic = false
+ );
+
+private:
+ inline static constexpr auto frame_folder = "frames";
+
+ [[nodiscard]] static ztu::result frame_id_from_filename(
+ std::string_view filename
+ );
+
+ [[nodiscard]] static std::error_code load_point_file(
+ const std::filesystem::path& filename,
+ dynamic_point_cloud_buffer& point_cloud
+ );
+
+ static void transform_point_cloud(
+ std::span points,
+ const glm::mat4& pose
+ );
+
+ [[nodiscard]] static ztu::result parent_directory(std::string_view path);
+
+
+};
diff --git a/include/assets/data_loaders/kitti_pose_loader.hpp b/include/assets/data_loaders/kitti_pose_loader.hpp
new file mode 100644
index 0000000..ce553c1
--- /dev/null
+++ b/include/assets/data_loaders/kitti_pose_loader.hpp
@@ -0,0 +1,37 @@
+#pragma once
+
+#include
+
+#include "assets/dynamic_data_store.hpp"
+#include "assets/prefetch_lookup.hpp"
+#include "assets/prefetch_queue.hpp"
+#include "util/string_list.hpp"
+#include "assets/dynamic_data_stores/dynamic_pose_store.hpp"
+#include "assets/dynamic_read_buffers/dynamic_pose_buffer.hpp"
+#include "assets/prefetch_lookups/pose_prefetch_lookup.hpp"
+
+struct kitti_pose_loader
+{
+ static constexpr auto name = std::string_view("kitti_pose");
+
+ [[nodiscard]] static std::error_code prefetch(
+ const file_dir_list& paths,
+ prefetch_queue& queue
+ );
+
+ [[nodiscard]] static std::error_code load(
+ dynamic_pose_buffer& buffer,
+ const file_dir_list& paths,
+ prefetch_lookup& id_lookup,
+ dynamic_data_store& store,
+ bool pedantic = false
+ );
+
+private:
+ static constexpr auto pose_filename = std::string_view{ "pose.txt" };
+
+ static std::error_code parse_pose(
+ std::ifstream& in,
+ dynamic_pose_buffer& pose
+ );
+};
\ No newline at end of file
diff --git a/include/assets/data_loaders/mtl_loader.hpp b/include/assets/data_loaders/mtl_loader.hpp
new file mode 100644
index 0000000..dd2df5f
--- /dev/null
+++ b/include/assets/data_loaders/mtl_loader.hpp
@@ -0,0 +1,56 @@
+#pragma once
+
+#include
+#include
+
+#include "assets/dynamic_data_store.hpp"
+#include "assets/prefetch_lookup.hpp"
+#include "assets/prefetch_queue.hpp"
+#include "assets/dynamic_read_buffers/dynamic_material_buffer.hpp"
+#include "assets/dynamic_data_stores/dynamic_material_library_store.hpp"
+#include "assets/dynamic_data_stores/dynamic_material_store.hpp"
+#include "util/string_lookup.hpp"
+#include "util/result.hpp"
+
+namespace mtl_loader_error {
+
+enum class codes {
+ ok = 0,
+ mtl_cannot_open_file,
+ mtl_cannot_open_texture,
+ mtl_malformed_ambient_color,
+ mtl_malformed_diffuse_color,
+ mtl_malformed_specular_color,
+ mtl_malformed_specular_exponent,
+ mtl_malformed_dissolve,
+ mlt_unknown_line_begin
+};
+
+} // namespace mtl_loader_error
+
+class mtl_loader {
+public:
+ static constexpr auto name = std::string_view("mtl");
+
+ std::optional find_id(std::string_view name);
+
+ void clear_name_lookup();
+
+ [[nodiscard]] static std::error_code prefetch(
+ const file_dir_list& paths,
+ prefetch_queue& queue
+ );
+
+ // THis is not very elegant, but right now I do not see a better solution...
+ [[nodiscard]] static std::error_code load(
+ dynamic_material_library_buffer& material_library_buffer,
+ const file_dir_list& paths,
+ prefetch_lookup& id_lookup,
+ dynamic_data_store& store,
+ bool pedantic = false
+ );
+
+
+private:
+ ztu::string_lookup m_id_lookup;
+};
diff --git a/include/assets/data_loaders/obj_loader.hpp b/include/assets/data_loaders/obj_loader.hpp
new file mode 100755
index 0000000..7bd95e6
--- /dev/null
+++ b/include/assets/data_loaders/obj_loader.hpp
@@ -0,0 +1,42 @@
+#pragma once
+
+#include
+#include
+#include
+#include "assets/dynamic_data_loaders/dynamic_material_loader.hpp"
+#include "assets/dynamic_data_stores/dynamic_mesh_store.hpp"
+#include "assets/prefetch_lookup.hpp"
+
+namespace obj_loader_error {
+
+enum class codes {
+ ok = 0,
+ obj_cannot_open_file,
+ obj_malformed_vertex,
+ obj_malformed_texture_coordinate,
+ obj_malformed_normal,
+ obj_malformed_face,
+ obj_face_index_out_of_range,
+ obj_unknown_line_begin
+};
+
+} // namespace obj_loader_error
+
+struct obj_loader {
+
+ static constexpr auto name = std::string_view("obj");
+
+ [[nodiscard]] static std::error_code prefetch(
+ const file_dir_list& paths,
+ prefetch_queue& queue
+ );
+
+ [[nodiscard]] static std::error_code load(
+ components::mesh_vertex::flags enabled_components,
+ dynamic_mesh_buffer& buffer,
+ const file_dir_list& paths,
+ prefetch_lookup& id_lookup,
+ dynamic_data_store& store,
+ bool pedantic = false
+ );
+};
diff --git a/include/assets/data_loaders/stl_loader.hpp b/include/assets/data_loaders/stl_loader.hpp
new file mode 100644
index 0000000..4c0b1f1
--- /dev/null
+++ b/include/assets/data_loaders/stl_loader.hpp
@@ -0,0 +1,30 @@
+#pragma once
+
+#include
+#include
+#include
+
+#include "assets/dynamic_data_store.hpp"
+#include "assets/dynamic_read_buffers/dynamic_mesh_buffer.hpp"
+#include "assets/dynamic_data_stores/dynamic_mesh_store.hpp"
+#include "assets/prefetch_lookup.hpp"
+#include "assets/prefetch_queue.hpp"
+
+struct stl_loader {
+
+ static constexpr auto name = std::string_view("stl");
+
+ [[nodiscard]] static std::error_code prefetch(
+ const file_dir_list& paths,
+ prefetch_queue& queue
+ );
+
+ [[nodiscard]] static std::error_code load(
+ // space stuff that has to persist
+ dynamic_mesh_buffer& buffer,
+ const file_dir_list& paths,
+ prefetch_lookup& id_lookup,
+ dynamic_data_store& store,
+ bool pedantic = false
+ );
+};
diff --git a/include/assets/data_loaders/threedtk_pose_loader.hpp b/include/assets/data_loaders/threedtk_pose_loader.hpp
new file mode 100644
index 0000000..7365857
--- /dev/null
+++ b/include/assets/data_loaders/threedtk_pose_loader.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include
+
+#include "assets/dynamic_data_store.hpp"
+#include "assets/prefetch_lookup.hpp"
+#include "assets/prefetch_queue.hpp"
+#include "assets/dynamic_read_buffers/dynamic_pose_buffer.hpp"
+#include "util/string_list.hpp"
+#include "util/result.hpp"
+#include "assets/prefetch_lookups/pose_prefetch_lookup.hpp"
+
+struct threedtk_pose_loader
+{
+ static constexpr auto name = std::string_view("3dtk_pose");
+
+ [[nodiscard]] static std::error_code prefetch(
+ const file_dir_list& paths,
+ prefetch_queue& queue
+ );
+
+ [[nodiscard]] static std::error_code load(
+ dynamic_pose_buffer& buffer,
+ const file_dir_list& paths,
+ prefetch_lookup& id_lookup,
+ dynamic_data_store& store,
+ bool pedantic = false
+ );
+
+protected:
+ static std::error_code parse_transform_info(
+ std::ifstream& in,
+ std::string& line,
+ std::array& transform_info
+ );
+
+ static ztu::result parse_index(
+ std::string_view filename
+ );
+};
diff --git a/include/assets/data_loaders/uos_loader.hpp b/include/assets/data_loaders/uos_loader.hpp
new file mode 100644
index 0000000..7d1e6ae
--- /dev/null
+++ b/include/assets/data_loaders/uos_loader.hpp
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "generic/generic_3dtk_loader.hpp"
+
+struct uos_loader : generic_3dtk_loader
+{
+ static constexpr auto name = std::string_view("uos");
+};
+
diff --git a/include/assets/data_loaders/uos_normal_loader.hpp b/include/assets/data_loaders/uos_normal_loader.hpp
new file mode 100644
index 0000000..5c95b04
--- /dev/null
+++ b/include/assets/data_loaders/uos_normal_loader.hpp
@@ -0,0 +1,8 @@
+#pragma once
+
+#include "generic/generic_3dtk_loader.hpp"
+
+struct uos_normal_loader : generic_3dtk_loader
+{
+ static constexpr auto name = std::string_view("uos_normal");
+};
diff --git a/include/assets/data_loaders/uos_rgb_loader.hpp b/include/assets/data_loaders/uos_rgb_loader.hpp
new file mode 100644
index 0000000..f49b79e
--- /dev/null
+++ b/include/assets/data_loaders/uos_rgb_loader.hpp
@@ -0,0 +1,8 @@
+#pragma once
+
+#include "generic/generic_3dtk_loader.hpp"
+
+struct uos_rgb_loader : generic_3dtk_loader
+{
+ static constexpr auto name = std::string_view("uos_rgb");
+};
diff --git a/include/assets/data_loaders/uosr_loader.hpp b/include/assets/data_loaders/uosr_loader.hpp
new file mode 100644
index 0000000..c59f6e5
--- /dev/null
+++ b/include/assets/data_loaders/uosr_loader.hpp
@@ -0,0 +1,8 @@
+#pragma once
+
+#include "generic/generic_3dtk_loader.hpp"
+
+struct uosr_loader : generic_3dtk_loader
+{
+ static constexpr auto name = std::string_view("uosr");
+};
diff --git a/include/assets/dynamic_data_loaders/dynamic_material_library_loader.hpp b/include/assets/dynamic_data_loaders/dynamic_material_library_loader.hpp
new file mode 100644
index 0000000..8c508ab
--- /dev/null
+++ b/include/assets/dynamic_data_loaders/dynamic_material_library_loader.hpp
@@ -0,0 +1,36 @@
+#pragma once
+
+#include "assets/prefetch_queue.hpp"
+#include "assets/components/material_components.hpp"
+#include "assets/dynamic_read_buffers/dynamic_material_library_buffer.hpp"
+#include "assets/dynamic_data_stores/dynamic_material_library_store.hpp"
+#include "assets/prefetch_lookups/material_library_prefetch_lookup.hpp"
+#include "generic/base_dynamic_loader.hpp"
+
+#include "assets/data_loaders/mtl_loader.hpp"
+#include "util/string_list.hpp"
+
+class dynamic_material_library_loader : public base_dynamic_loader<
+ components::material::flags,
+ mtl_loader
+> {
+public:
+
+ [[nodiscard]] std::error_code prefetch(
+ loader_id_type loader_id,
+ const ztu::string_list& directories,
+ prefetch_queue& queue
+ );
+
+ [[nodiscard]] std::error_code load(
+ loader_id_type loader_id,
+ const ztu::string_list& directories,
+ dynamic_material_library_store& store,
+ dynamic_material_store& material_store,
+ material_library_prefetch_lookup& id_lookup,
+ bool pedantic = false
+ );
+
+private:
+ dynamic_material_library_buffer m_buffer{};
+};
diff --git a/include/assets/dynamic_data_loaders/dynamic_material_loader.hpp b/include/assets/dynamic_data_loaders/dynamic_material_loader.hpp
new file mode 100644
index 0000000..934f87f
--- /dev/null
+++ b/include/assets/dynamic_data_loaders/dynamic_material_loader.hpp
@@ -0,0 +1,34 @@
+#pragma once
+
+#include "assets/prefetch_queue.hpp"
+#include "assets/components/material_components.hpp"
+#include "generic/base_dynamic_loader.hpp"
+
+#include "assets/data_loaders/mtl_loader.hpp"
+#include "assets/dynamic_data_stores/dynamic_material_store.hpp"
+#include "assets/prefetch_lookups/material_prefetch_lookup.hpp"
+#include "util/string_list.hpp"
+
+class dynamic_material_loader : public base_dynamic_loader<
+ components::material::flags
+ // TODO no loaders
+> {
+public:
+
+ [[nodiscard]] std::error_code prefetch(
+ loader_id_type loader_id,
+ const ztu::string_list& directories,
+ prefetch_queue& queue
+ );
+
+ [[nodiscard]] std::error_code load(
+ loader_id_type loader_id,
+ const ztu::string_list& directories,
+ dynamic_material_store& store,
+ material_prefetch_lookup& id_lookup,
+ bool pedantic = false
+ );
+
+private:
+ dynamic_material_buffer m_buffer{};
+};
diff --git a/include/assets/dynamic_data_loaders/dynamic_mesh_loader.hpp b/include/assets/dynamic_data_loaders/dynamic_mesh_loader.hpp
new file mode 100644
index 0000000..3d02ed4
--- /dev/null
+++ b/include/assets/dynamic_data_loaders/dynamic_mesh_loader.hpp
@@ -0,0 +1,35 @@
+#pragma once
+
+#include "generic/base_dynamic_loader.hpp"
+#include
+
+#include "assets/dynamic_read_buffers/dynamic_mesh_buffer.hpp"
+#include "assets/dynamic_data_stores/dynamic_mesh_store.hpp"
+#include "assets/data_loaders/obj_loader.hpp"
+#include "assets/data_loaders/stl_loader.hpp"
+#include "assets/prefetch_lookups/mesh_prefetch_lookup.hpp"
+
+
+class dynamic_mesh_loader : public base_dynamic_loader<
+ components::mesh_vertex::flags,
+ obj_loader,
+ stl_loader
+> {
+public:
+ [[nodiscard]] std::error_code prefetch(
+ loader_id_type loader_id,
+ const ztu::string_list& directories,
+ prefetch_queue& queue
+ );
+
+ [[nodiscard]] std::error_code load(
+ loader_id_type loader_id,
+ const ztu::string_list& directories,
+ dynamic_mesh_store& store,
+ mesh_prefetch_lookup& id_lookup,
+ bool pedantic = false
+ );
+
+private:
+ dynamic_mesh_buffer m_buffer{};
+};
diff --git a/include/assets/dynamic_data_loaders/dynamic_point_cloud_loader.hpp b/include/assets/dynamic_data_loaders/dynamic_point_cloud_loader.hpp
new file mode 100644
index 0000000..7c7b601
--- /dev/null
+++ b/include/assets/dynamic_data_loaders/dynamic_point_cloud_loader.hpp
@@ -0,0 +1,46 @@
+#pragma once
+
+#include
+#include
+
+#include "assets/prefetch_queue.hpp"
+#include "generic/base_dynamic_loader.hpp"
+#include "assets/dynamic_read_buffers/dynamic_point_cloud_buffer.hpp"
+#include "assets/dynamic_data_stores/dynamic_point_cloud_store.hpp"
+
+#include "assets/data_loaders/kitti_loader.hpp"
+#include "assets/data_loaders/uos_loader.hpp"
+#include "assets/data_loaders/uos_normal_loader.hpp"
+#include "assets/data_loaders/uos_rgb_loader.hpp"
+#include "assets/data_loaders/uosr_loader.hpp"
+#include "assets/prefetch_lookups/point_cloud_prefetch_lookup.hpp"
+
+#include "util/string_list.hpp"
+
+class dynamic_point_cloud_loader : public base_dynamic_loader<
+ components::point_cloud_vertex::flags,
+ kitti_loader,
+ uos_loader,
+ uos_normal_loader,
+ uos_rgb_loader,
+ uos_loader,
+ uosr_loader
+> {
+public:
+ [[nodiscard]] std::error_code prefetch(
+ loader_id_type loader_id,
+ const ztu::string_list& directories,
+ prefetch_queue& queue
+ );
+
+ [[nodiscard]] std::error_code load(
+ loader_id_type loader_id,
+ const ztu::string_list& directories,
+ dynamic_point_cloud_store& store,
+ point_cloud_prefetch_lookup& id_lookup,
+ bool pedantic = false
+ );
+
+private:
+ dynamic_point_cloud_buffer m_buffer{};
+};
diff --git a/include/assets/dynamic_data_loaders/dynamic_texture_loader.hpp b/include/assets/dynamic_data_loaders/dynamic_texture_loader.hpp
new file mode 100644
index 0000000..a703253
--- /dev/null
+++ b/include/assets/dynamic_data_loaders/dynamic_texture_loader.hpp
@@ -0,0 +1,60 @@
+#pragma once
+
+#include
+#include
+#include "util/uix.hpp"
+#include "util/id_type.hpp"
+#include "util/string_lookup.hpp"
+#include "util/result.hpp"
+
+#include "assets/components/texture_components.hpp"
+#include "assets/dynamic_read_buffers/dynamic_texture_buffer.hpp"
+#include "assets/dynamic_data_stores/dynamic_texture_store.hpp"
+#include "assets/dynamic_data_loader_ctx.hpp"
+#include "assets/prefetch_queue.hpp"
+#include "assets/prefetch_lookups/texture_prefetch_lookup.hpp"
+#include "util/string_list.hpp"
+
+/*
+* [[nodiscard]] std::error_code prefetch(
+loader_id_type loader_id,
+const ztu::string_list& directories,
+prefetch_queue& queue
+);
+
+[[nodiscard]] std::error_code load(
+loader_id_type loader_id,
+const ztu::string_list& directories,
+dynamic_point_cloud_store& store,
+point_cloud_prefetch_lookup& id_lookup,
+bool pedantic = false
+);
+*/
+
+class dynamic_texture_loader
+{
+public:
+ using loader_id_type = ztu::id_type_for;
+
+ explicit dynamic_texture_loader(components::texture::flags enabled_components);
+
+ [[nodiscard]] std::optional find_loader(const std::string_view& name);
+
+ [[nodiscard]] std::error_code prefetch(
+ loader_id_type loader_id,
+ const ztu::string_list& directories,
+ prefetch_queue& queue
+ );
+
+ [[nodiscard]] std::error_code load(
+ loader_id_type loader_id,
+ const ztu::string_list& directories,
+ dynamic_texture_store& store,
+ texture_prefetch_lookup& id_lookup,
+ bool pedantic = false
+ );
+
+private:
+ ztu::string_lookup m_loader_id_lookup{};
+ components::texture::flags m_enabled_components{ components::texture::flags::none };
+};
diff --git a/include/assets/dynamic_data_loaders/generic/base_dynamic_loader.hpp b/include/assets/dynamic_data_loaders/generic/base_dynamic_loader.hpp
new file mode 100644
index 0000000..bf0d819
--- /dev/null
+++ b/include/assets/dynamic_data_loaders/generic/base_dynamic_loader.hpp
@@ -0,0 +1,39 @@
+#pragma once
+
+#include
+#include
+
+#include "assets/dynamic_data_stores/dynamic_point_cloud_store.hpp"
+#include "util/uix.hpp"
+#include "util/string_lookup.hpp"
+#include "util/id_type.hpp"
+#include "util/result.hpp"
+
+template
+class base_dynamic_loader
+{
+public:
+ using loader_id_type = ztu::id_type_for;
+
+ explicit base_dynamic_loader(C enabled_components);
+
+ [[nodiscard]] std::optional find_loader(std::string_view name);
+
+ [[nodiscard]] static consteval std::optional find_loader_static(std::string_view name);
+
+ template
+ auto& get_loader();
+
+protected:
+
+ template
+ ztu::result invoke_with_matching_loader(loader_id_type loader_id, F&& f);
+
+ std::tuple m_loaders{};
+ ztu::string_lookup m_loader_id_lookup{};
+ C m_enabled_components{ 0 };
+};
+
+#define INCLUDE_BASE_DYNAMIC_LOADER_IMPLEMENTATION
+#include "assets/dynamic_data_loaders/generic/base_dynamic_loader.ipp"
+#undef INCLUDE_BASE_DYNAMIC_LOADER_IMPLEMENTATION
diff --git a/include/assets/dynamic_data_stores/dynamic_material_library_store.hpp b/include/assets/dynamic_data_stores/dynamic_material_library_store.hpp
new file mode 100644
index 0000000..a180507
--- /dev/null
+++ b/include/assets/dynamic_data_stores/dynamic_material_library_store.hpp
@@ -0,0 +1,6 @@
+#pragma once
+
+#include "generic/generic_dynamic_store.hpp"
+#include "assets/dynamic_read_buffers/dynamic_material_library_buffer.hpp"
+
+using dynamic_material_library_store = generic_dynamic_store;
diff --git a/include/assets/dynamic_data_stores/dynamic_material_store.hpp b/include/assets/dynamic_data_stores/dynamic_material_store.hpp
new file mode 100644
index 0000000..cfb849f
--- /dev/null
+++ b/include/assets/dynamic_data_stores/dynamic_material_store.hpp
@@ -0,0 +1,37 @@
+#pragma once
+
+#include "dynamic_texture_store.hpp"
+#include "generic/generic_dynamic_component_store.hpp"
+#include "assets/dynamic_read_buffers/dynamic_material_buffer.hpp"
+
+class dynamic_material_store {
+ using store_type = generic_dynamic_component_store<
+ components::material::flags,
+ components::material::surface_properties,
+ components::material::transparency,
+ dynamic_texture_store::id_type,
+ dynamic_texture_store::id_type,
+ dynamic_texture_store::id_type,
+ dynamic_texture_store::id_type,
+ dynamic_texture_store::id_type,
+ dynamic_texture_store::id_type
+ >;
+
+public:
+ using id_type = store_type::id_type;
+ using iterator_type = store_type::iterator_type;
+ using const_iterator = store_type::const_iterator;
+
+ id_type add(const dynamic_material_buffer& data);
+
+ [[nodiscard]] std::pair find(id_type id);
+
+ [[nodiscard]] std::pair find(id_type id) const;
+
+ void remove(const iterator_type& it);
+
+ void clear();
+
+private:
+ store_type m_store;
+};
diff --git a/include/assets/dynamic_data_stores/dynamic_mesh_store.hpp b/include/assets/dynamic_data_stores/dynamic_mesh_store.hpp
new file mode 100644
index 0000000..2268d97
--- /dev/null
+++ b/include/assets/dynamic_data_stores/dynamic_mesh_store.hpp
@@ -0,0 +1,37 @@
+#pragma once
+
+#include "assets/dynamic_data_stores/generic/generic_dynamic_indexed_component_array_store.hpp"
+
+#include "assets/components/mesh_vertex_components.hpp"
+#include "assets/dynamic_read_buffers/dynamic_mesh_buffer.hpp"
+
+class dynamic_mesh_store
+{
+ using store_type = generic_dynamic_indexed_component_array_store<
+ components::mesh_vertex::flags,
+ ztu::u32,
+ components::mesh_vertex::position,
+ components::mesh_vertex::normal,
+ components::mesh_vertex::tex_coord,
+ components::mesh_vertex::color,
+ components::mesh_vertex::reflectance
+ >;
+
+public:
+ using id_type = store_type::id_type;
+ using iterator_type = store_type::iterator_type;
+ using const_iterator = store_type::const_iterator;
+
+ id_type add(const dynamic_mesh_buffer& mesh_buffer);
+
+ [[nodiscard]] std::pair find(id_type id);
+
+ [[nodiscard]] std::pair find(id_type id) const;
+
+ void remove(const iterator_type& it);
+
+ void clear();
+
+private:
+ store_type m_store;
+};
\ No newline at end of file
diff --git a/include/assets/dynamic_data_stores/dynamic_point_cloud_store.hpp b/include/assets/dynamic_data_stores/dynamic_point_cloud_store.hpp
new file mode 100644
index 0000000..f86b9c2
--- /dev/null
+++ b/include/assets/dynamic_data_stores/dynamic_point_cloud_store.hpp
@@ -0,0 +1,36 @@
+#pragma once
+
+#include "assets/dynamic_data_stores/generic/generic_dynamic_component_array_store.hpp"
+
+#include "assets/components/point_cloud_vertex_components.hpp"
+#include "assets/dynamic_read_buffers/dynamic_point_cloud_buffer.hpp"
+
+
+class dynamic_point_cloud_store
+{
+ using store_type = generic_dynamic_component_array_store<
+ components::point_cloud_vertex::flags,
+ components::point_cloud_vertex::position,
+ components::point_cloud_vertex::normal,
+ components::point_cloud_vertex::color,
+ components::point_cloud_vertex::reflectance
+ >;
+
+public:
+ using id_type = store_type::id_type;
+ using iterator_type = store_type::iterator_type;
+ using const_iterator = store_type::const_iterator;
+
+ id_type add(const dynamic_point_cloud_buffer& point_cloud_buffer);
+
+ [[nodiscard]] std::pair find(id_type id);
+
+ [[nodiscard]] std::pair find(id_type id) const;
+
+ void remove(const iterator_type& it);
+
+ void clear();
+
+private:
+ store_type m_store;
+};
diff --git a/include/assets/dynamic_data_stores/dynamic_pose_store.hpp b/include/assets/dynamic_data_stores/dynamic_pose_store.hpp
new file mode 100644
index 0000000..9c59d68
--- /dev/null
+++ b/include/assets/dynamic_data_stores/dynamic_pose_store.hpp
@@ -0,0 +1,6 @@
+#pragma once
+
+#include "generic/generic_dynamic_store.hpp"
+#include "glm/mat4x4.hpp"
+
+using dynamic_pose_store = generic_dynamic_store;
diff --git a/include/assets/dynamic_data_stores/dynamic_shader_store.hpp b/include/assets/dynamic_data_stores/dynamic_shader_store.hpp
new file mode 100644
index 0000000..1b88e2b
--- /dev/null
+++ b/include/assets/dynamic_data_stores/dynamic_shader_store.hpp
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "generic/generic_dynamic_store.hpp"
+#include "glm/mat4x4.hpp"
+
+class dynamic_shader_store {
+
+
+};
\ No newline at end of file
diff --git a/include/assets/dynamic_data_stores/dynamic_texture_store.hpp b/include/assets/dynamic_data_stores/dynamic_texture_store.hpp
new file mode 100644
index 0000000..52437c3
--- /dev/null
+++ b/include/assets/dynamic_data_stores/dynamic_texture_store.hpp
@@ -0,0 +1,6 @@
+#pragma once
+
+#include "generic/generic_dynamic_store.hpp"
+#include "assets/dynamic_read_buffers/dynamic_texture_buffer.hpp"
+
+using dynamic_texture_store = generic_dynamic_store;
diff --git a/include/assets/dynamic_data_stores/dynamic_vertex_store.hpp b/include/assets/dynamic_data_stores/dynamic_vertex_store.hpp
new file mode 100644
index 0000000..77f0e5c
--- /dev/null
+++ b/include/assets/dynamic_data_stores/dynamic_vertex_store.hpp
@@ -0,0 +1,37 @@
+#pragma once
+
+#include
+#include
+#include
+#include "util/id_type.hpp"
+#include "util/uix.hpp"
+
+#include "GL/glew.h"
+
+template
+class dynamic_vertex_store {
+public:
+ using id_type = ztu::id_type_for;
+
+ void add(
+ C component_flags,
+ std::span... components
+ );
+
+ void build_vertex_buffer(
+ std::vector& vertex_buffer,
+ std::size_t& component_count,
+ std::array& component_types,
+ std::array& component_lengths,
+ GLsizei& stride
+ ) const;
+
+protected:
+ std::tuple...> m_component_buffers{};
+ std::vector vertex_counts;
+ std::vector m_components{ 0 };
+};
+
+#define INCLUDE_DYNAMIC_MODEL_DATA_IMPLEMENTATION
+#include "assets/dynamic_read_buffers/dynamic_model_buffer.ipp"
+#undef INCLUDE_DYNAMIC_MODEL_DATA_IMPLEMENTATION
diff --git a/include/assets/dynamic_data_stores/generic/generic_dynamic_component_array_store.hpp b/include/assets/dynamic_data_stores/generic/generic_dynamic_component_array_store.hpp
new file mode 100644
index 0000000..94dec73
--- /dev/null
+++ b/include/assets/dynamic_data_stores/generic/generic_dynamic_component_array_store.hpp
@@ -0,0 +1,149 @@
+#pragma once
+
+#include
+#include
+
+#include "util/uix.hpp"
+#include "util/id_type.hpp"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+template
+class generic_dynamic_component_array_store;
+
+template
+class component_array_iterator {
+public:
+ using value_type = std::tuple...>;
+ using size_type = std::size_t;
+ using count_type = ztu::u32;
+ using flag_count_type = std::pair;
+ using component_array_pointer_type = std::tuple...>;
+ using flag_count_pointer_type = const flag_count_type*;
+ using offsets_type = std::array;
+ using difference_type = std::ptrdiff_t;
+ using pointer = value_type*;
+ using reference = value_type;
+ using iterator_category = std::random_access_iterator_tag;
+
+private:
+ friend generic_dynamic_component_array_store;
+
+ component_array_iterator(
+ component_array_pointer_type components,
+ flag_count_pointer_type flags,
+ std::size_t index,
+ const offsets_type& offsets
+ );
+
+public:
+ constexpr component_array_iterator() noexcept = default;
+
+ constexpr component_array_iterator(const component_array_iterator&) noexcept = default;
+ constexpr component_array_iterator(component_array_iterator&&) noexcept = default;
+
+ constexpr component_array_iterator& operator=(const component_array_iterator&) noexcept = default;
+ constexpr component_array_iterator& operator=(component_array_iterator&&) noexcept = default;
+
+ reference operator*() const;
+
+ component_array_iterator& operator++();
+ component_array_iterator operator++(int);
+ component_array_iterator& operator--();
+ component_array_iterator operator--(int);
+
+ component_array_iterator& operator+=(difference_type n);
+ component_array_iterator& operator-=(difference_type n);
+ component_array_iterator operator+(difference_type n) const;
+ component_array_iterator operator-(difference_type n) const;
+ difference_type operator-(const component_array_iterator& other) const;
+
+ reference operator[](difference_type n) const;
+
+ bool operator==(const component_array_iterator& other) const;
+ bool operator!=(const component_array_iterator& other) const;
+ bool operator<(const component_array_iterator& other) const;
+ bool operator<=(const component_array_iterator& other) const;
+ bool operator>(const component_array_iterator& other) const;
+ bool operator>=(const component_array_iterator& other) const;
+
+protected:
+ template
+ static bool is_component_enabled(C flag);
+
+ template
+ void calc_offsets(std::index_sequence, difference_type n);
+
+ template
+ reference dereference(std::index_sequence) const;
+
+ template
+ std::tuple_element_t get_span() const;
+
+private:
+ value_type m_components{};
+ const flag_count_type* m_flag_counts{};
+ size_type m_index{};
+ offsets_type m_offsets{};
+};
+
+template
+class generic_dynamic_component_array_store
+{
+public:
+ using id_type = ztu::id_type_for;
+ using count_type = ztu::u32;
+ using iterator_type = component_array_iterator;
+ using const_iterator = component_array_iterator...>;
+ using view_type = std::ranges::subrange;
+ using const_view_type = std::ranges::subrange;
+
+ id_type add(const std::tuple...>& component_arrays);
+
+ [[nodiscard]] std::pair find(id_type id);
+
+ [[nodiscard]] std::pair find(id_type id) const;
+
+ void remove(const iterator_type& it);
+
+ void clear();
+
+ iterator_type begin();
+
+ iterator_type end();
+
+ const_iterator begin() const;
+
+ const_iterator end() const;
+
+ const_iterator cbegin() const;
+
+ const_iterator cend() const;
+
+ view_type view();
+
+ const_view_type view() const;
+
+protected:
+ std::tuple...> data_ptrs();
+
+ std::tuple>...> data_ptrs() const;
+
+ std::array data_counts() const;
+
+private:
+ std::tuple...> m_component_arrays;
+ std::vector> m_component_flag_counts;
+ std::vector m_ids;
+ id_type m_next_data_id{ 1 };
+};
+
+#define INCLUDE_GENERIC_DYNAMIC_COMPONENT_ARRAY_STORE_IMPLEMENTATION
+#include "assets/dynamic_data_stores/generic/generic_dynamic_component_array_store.ipp"
+#undef INCLUDE_GENERIC_DYNAMIC_COMPONENT_ARRAY_STORE_IMPLEMENTATION
diff --git a/include/assets/dynamic_data_stores/generic/generic_dynamic_component_store.hpp b/include/assets/dynamic_data_stores/generic/generic_dynamic_component_store.hpp
new file mode 100644
index 0000000..0dbac6f
--- /dev/null
+++ b/include/assets/dynamic_data_stores/generic/generic_dynamic_component_store.hpp
@@ -0,0 +1,147 @@
+#pragma once
+
+#include
+#include
+
+#include "util/uix.hpp"
+#include "util/id_type.hpp"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+template
+class generic_dynamic_component_store;
+
+template
+class component_iterator {
+public:
+
+
+ using value_type = std::tuple...>;
+ using size_type = std::size_t;
+ using offsets_type = std::array;
+ using difference_type = std::ptrdiff_t;
+ using pointer = value_type*;
+ using reference = value_type;
+ using iterator_category = std::random_access_iterator_tag;
+
+private:
+ friend generic_dynamic_component_store;
+
+ component_iterator(
+ value_type components,
+ const C* flags,
+ std::size_t index,
+ const offsets_type& offsets
+ );
+
+public:
+
+ constexpr component_iterator() noexcept = default;
+
+ constexpr component_iterator(const component_iterator&) noexcept = default;
+ constexpr component_iterator(component_iterator&&) noexcept = default;
+
+ constexpr component_iterator& operator=(const component_iterator&) noexcept = default;
+ constexpr component_iterator& operator=(component_iterator&&) noexcept = default;
+
+ reference operator*() const;
+
+ component_iterator& operator++();
+ component_iterator operator++(int);
+ component_iterator& operator--();
+ component_iterator operator--(int);
+
+ component_iterator& operator+=(difference_type n);
+ component_iterator& operator-=(difference_type n);
+ component_iterator operator+(difference_type n) const;
+ component_iterator operator-(difference_type n) const;
+ difference_type operator-(const component_iterator& other) const;
+
+ reference operator[](difference_type n) const;
+
+ bool operator==(const component_iterator& other) const;
+ bool operator!=(const component_iterator& other) const;
+ bool operator<(const component_iterator& other) const;
+ bool operator<=(const component_iterator& other) const;
+ bool operator>(const component_iterator& other) const;
+ bool operator>=(const component_iterator& other) const;
+
+protected:
+ template
+ static bool is_component_enabled(C flag);
+
+ template
+ void calc_offsets(std::index_sequence, difference_type n);
+
+ template
+ reference dereference(std::index_sequence) const;
+
+ template
+ std::tuple_element_t get_pointer() const;
+
+private:
+ value_type m_components{};
+ const C* m_flags{};
+ size_type m_index{};
+ offsets_type m_offsets{};
+};
+
+template
+class generic_dynamic_component_store
+{
+public:
+ using id_type = ztu::id_type_for;
+ using iterator_type = component_iterator;
+ using const_iterator = component_iterator...>;
+ using view_type = std::ranges::subrange;
+ using const_view_type = std::ranges::subrange;
+
+ id_type add(const std::tuple...>& data);
+
+ [[nodiscard]] std::pair find(id_type id);
+
+ [[nodiscard]] std::pair find(id_type id) const;
+
+ void remove(const iterator_type& it);
+
+ void clear();
+
+ iterator_type begin();
+
+ iterator_type end();
+
+ const_iterator begin() const;
+
+ const_iterator end() const;
+
+ const_iterator cbegin() const;
+
+ const_iterator cend() const;
+
+ view_type view();
+
+ const_view_type view() const;
+
+protected:
+ std::tuple...> data_ptrs();
+
+ std::tuple>...> data_ptrs() const;
+
+ std::array data_counts() const;
+
+private:
+ std::tuple...> m_components;
+ std::vector m_component_flags;
+ std::vector m_ids;
+ id_type m_next_data_id{ 1 };
+};
+
+#define INCLUDE_GENERIC_DYNAMIC_COMPONENT_STORE_IMPLEMENTATION
+#include "assets/dynamic_data_stores/generic_dynamic_component_store.ipp"
+#undef INCLUDE_GENERIC_DYNAMIC_COMPONENT_STORE_IMPLEMENTATION
diff --git a/include/assets/dynamic_data_stores/generic/generic_dynamic_indexed_component_array_store.hpp b/include/assets/dynamic_data_stores/generic/generic_dynamic_indexed_component_array_store.hpp
new file mode 100644
index 0000000..8c47f0d
--- /dev/null
+++ b/include/assets/dynamic_data_stores/generic/generic_dynamic_indexed_component_array_store.hpp
@@ -0,0 +1,157 @@
+#pragma once
+
+#include
+#include
+
+#include "util/uix.hpp"
+#include "util/id_type.hpp"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+template
+class generic_dynamic_indexed_component_array_store;
+
+template
+class indexed_component_array_iterator {
+public:
+ using index_type = I;
+ using value_type = std::tuple, std::span...>;
+ using size_type = std::size_t;
+ using count_type = ztu::u32;
+ using flag_count_type = std::tuple;
+ using index_array_pointer_type = const index_type*;
+ using component_array_pointer_type = std::tuple...>;
+ using flag_count_pointer_type = const flag_count_type*;
+
+ using offsets_type = std::array;
+ using difference_type = std::ptrdiff_t;
+ using pointer = value_type*;
+ using reference = value_type;
+ using iterator_category = std::random_access_iterator_tag;
+
+private:
+ friend generic_dynamic_indexed_component_array_store;
+
+ indexed_component_array_iterator(
+ index_array_pointer_type indices,
+ const component_array_pointer_type& components,
+ flag_count_pointer_type flag_counts,
+ std::size_t index,
+ const offsets_type& offsets
+ );
+
+public:
+ constexpr indexed_component_array_iterator() noexcept = default;
+
+ constexpr indexed_component_array_iterator(const indexed_component_array_iterator&) noexcept = default;
+ constexpr indexed_component_array_iterator(indexed_component_array_iterator&&) noexcept = default;
+
+ constexpr indexed_component_array_iterator& operator=(const indexed_component_array_iterator&) noexcept = default;
+ constexpr indexed_component_array_iterator& operator=(indexed_component_array_iterator&&) noexcept = default;
+
+ reference operator*() const;
+
+ indexed_component_array_iterator& operator++();
+ indexed_component_array_iterator operator++(int);
+ indexed_component_array_iterator& operator--();
+ indexed_component_array_iterator operator--(int);
+
+ indexed_component_array_iterator& operator+=(difference_type n);
+ indexed_component_array_iterator& operator-=(difference_type n);
+ indexed_component_array_iterator operator+(difference_type n) const;
+ indexed_component_array_iterator operator-(difference_type n) const;
+ difference_type operator-(const indexed_component_array_iterator& other) const;
+
+ reference operator[](difference_type n) const;
+
+ bool operator==(const indexed_component_array_iterator& other) const;
+ bool operator!=(const indexed_component_array_iterator& other) const;
+ bool operator<(const indexed_component_array_iterator& other) const;
+ bool operator<=(const indexed_component_array_iterator& other) const;
+ bool operator>(const indexed_component_array_iterator& other) const;
+ bool operator>=(const indexed_component_array_iterator& other) const;
+
+protected:
+ template
+ static bool is_component_enabled(C flag);
+
+ template
+ void calc_offsets(std::index_sequence, difference_type n);
+
+ template
+ reference dereference(std::index_sequence) const;
+
+private:
+ index_array_pointer_type m_indices{};
+ component_array_pointer_type m_components{};
+ flag_count_pointer_type m_flag_counts{};
+ size_type m_index{};
+ offsets_type m_offsets{};
+};
+
+template
+class generic_dynamic_indexed_component_array_store
+{
+public:
+ using id_type = ztu::id_type_for;
+ using count_type = ztu::u32;
+ using iterator_type = indexed_component_array_iterator;
+ using const_iterator = indexed_component_array_iterator...>;
+ using view_type = std::ranges::subrange;
+ using const_view_type = std::ranges::subrange;
+
+ id_type add(
+ std::span indices,
+ const std::tuple...>& component_arrays
+ );
+
+ [[nodiscard]] std::pair find(id_type id);
+
+ [[nodiscard]] std::pair find(id_type id) const;
+
+ void remove(const iterator_type& it);
+
+ void clear();
+
+ iterator_type begin();
+
+ iterator_type end();
+
+ const_iterator begin() const;
+
+ const_iterator end() const;
+
+ const_iterator cbegin() const;
+
+ const_iterator cend() const;
+
+ view_type view();
+
+ const_view_type view() const;
+
+protected:
+
+
+ std::tuple...> component_array_ptrs();
+
+ std::tuple>...> component_array_ptrs() const;
+
+ std::array array_counts() const;
+
+private:
+ std::vector m_indices;
+ std::tuple...> m_component_arrays;
+ std::vector> m_component_flag_counts;
+ std::vector m_ids;
+ id_type m_next_data_id{ 1 };
+};
+
+#define INCLUDE_GENERIC_DYNAMIC_INDEXED_COMPONENT_ARRAY_STORE_IMPLEMENTATION
+#include "assets/dynamic_data_stores/generic/generic_dynamic_indexed_component_array_store.ipp"
+#undef INCLUDE_GENERIC_DYNAMIC_INDEXED_COMPONENT_ARRAY_STORE_IMPLEMENTATION
diff --git a/include/assets/dynamic_data_stores/generic/generic_dynamic_store.hpp b/include/assets/dynamic_data_stores/generic/generic_dynamic_store.hpp
new file mode 100644
index 0000000..ebb6f4f
--- /dev/null
+++ b/include/assets/dynamic_data_stores/generic/generic_dynamic_store.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include
+#include
+
+#include "util/uix.hpp"
+#include "util/id_type.hpp"
+
+template
+class generic_dynamic_store
+{
+public:
+ using id_type = ztu::id_type_for;
+ using container_type = std::vector;
+ using iterator_type = typename container_type::iterator;
+ using const_iterator = typename container_type::const_iterator;
+
+ id_type add(const T& data);
+
+ [[nodiscard]] std::pair find(id_type id);
+
+ [[nodiscard]] std::pair find(id_type id) const;
+
+ [[nodiscard]] std::span data();
+
+ [[nodiscard]] std::span data() const;
+
+ void remove(iterator_type it);
+
+ void clear();
+
+private:
+ std::vector m_data;
+ std::vector m_ids;
+ id_type m_next_data_id{ 1 };
+};
+
+#define INCLUDE_GENERIC_DYNAMIC_STORE_IMPLEMENTATION
+#include "assets/dynamic_data_stores/generic_dynamic_store.ipp"
+#undef INCLUDE_GENERIC_DYNAMIC_STORE_IMPLEMENTATION
diff --git a/include/assets/dynamic_read_buffers/dynamic_material_buffer.hpp b/include/assets/dynamic_read_buffers/dynamic_material_buffer.hpp
new file mode 100755
index 0000000..d52e5b6
--- /dev/null
+++ b/include/assets/dynamic_read_buffers/dynamic_material_buffer.hpp
@@ -0,0 +1,48 @@
+#pragma once
+
+#include
+
+#include "assets/components/material_components.hpp"
+#include "assets/dynamic_data_stores/dynamic_texture_store.hpp"
+
+struct dynamic_material_buffer {
+
+ dynamic_material_buffer() = default;
+
+ components::material::surface_properties& initialized_surface_properties();
+
+ [[nodiscard]] std::optional& surface_properties();
+ [[nodiscard]] std::optional& transparency();
+ [[nodiscard]] std::optional& ambient_color_texture_id();
+ [[nodiscard]] std::optional& diffuse_color_texture_id();
+ [[nodiscard]] std::optional& specular_color_texture_id();
+ [[nodiscard]] std::optional& shininess_texture_id();
+ [[nodiscard]] std::optional& alpha_texture_id();
+ [[nodiscard]] std::optional& bump_texture_id();
+
+ [[nodiscard]] const std::optional& surface_properties() const;
+ [[nodiscard]] const std::optional& transparency() const;
+ [[nodiscard]] const std::optional& ambient_color_texture_id() const;
+ [[nodiscard]] const std::optional& diffuse_color_texture_id() const;
+ [[nodiscard]] const std::optional& specular_color_texture_id() const;
+ [[nodiscard]] const std::optional& shininess_texture_id() const;
+ [[nodiscard]] const std::optional& alpha_texture_id() const;
+ [[nodiscard]] const std::optional& bump_texture_id() const;
+
+ std::tuple<
+ std::optional,
+ std::optional,
+ std::optional,
+ std::optional,
+ std::optional,
+ std::optional,
+ std::optional,
+ std::optional
+ > data{
+ std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt
+ };
+};
+
+#define INCLUDE_DYNAMIC_MATERIAL_DATA_IMPLEMENTATION
+#include "assets/dynamic_read_buffers/dynamic_material_buffer.ipp"
+#undef INCLUDE_DYNAMIC_MATERIAL_DATA_IMPLEMENTATION
diff --git a/include/assets/dynamic_read_buffers/dynamic_material_library_buffer.hpp b/include/assets/dynamic_read_buffers/dynamic_material_library_buffer.hpp
new file mode 100644
index 0000000..13b03a6
--- /dev/null
+++ b/include/assets/dynamic_read_buffers/dynamic_material_library_buffer.hpp
@@ -0,0 +1,6 @@
+#pragma once
+
+#include "util/string_lookup.hpp"
+#include "assets/dynamic_data_stores/dynamic_material_store.hpp"
+
+using dynamic_material_library_buffer = ztu::string_lookup;
diff --git a/include/assets/dynamic_read_buffers/dynamic_mesh_buffer.hpp b/include/assets/dynamic_read_buffers/dynamic_mesh_buffer.hpp
new file mode 100644
index 0000000..b8491aa
--- /dev/null
+++ b/include/assets/dynamic_read_buffers/dynamic_mesh_buffer.hpp
@@ -0,0 +1,46 @@
+#pragma once
+
+#include
+#include
+
+#include "util/uix.hpp"
+#include "assets/components/mesh_vertex_components.hpp"
+#include "assets/dynamic_read_buffers/dynamic_vertex_buffer.hpp"
+#include "assets/dynamic_data_stores/dynamic_material_store.hpp"
+
+class dynamic_mesh_buffer : public dynamic_vertex_buffer<
+ components::mesh_vertex::flags,
+ components::mesh_vertex::position,
+ components::mesh_vertex::normal,
+ components::mesh_vertex::tex_coord,
+ components::mesh_vertex::color,
+ components::mesh_vertex::reflectance
+> {
+public:
+ using index_type = ztu::u32;
+ using triangle_type = std::array;
+
+ [[nodiscard]] std::vector& positions();
+ [[nodiscard]] std::vector& normals();
+ [[nodiscard]] std::vector& tex_coords();
+ [[nodiscard]] std::vector& colors();
+ [[nodiscard]] std::vector& reflectances();
+ [[nodiscard]] std::vector& triangles();
+ [[nodiscard]] auto& material_id();
+
+ [[nodiscard]] const std::vector& positions() const;
+ [[nodiscard]] const std::vector