diff --git a/CMakeLists.txt b/CMakeLists.txt index baa03aa..955e1a8 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,7 +128,7 @@ add_executable(z3d main.cpp include/assets/data/generic/component_array_set.hpp source/assets/data/texture_data.ipp source/assets/data/point_cloud_data.ipp - include/assets/file_parsers/mtl_loader.hpp + include/assets/file_parsers/mtl_parser.hpp include/assets/data_loaders/material_loader.hpp include/util/id_type.hpp include/assets/data_stores/generic/generic_basic_store.hpp @@ -137,7 +137,7 @@ add_executable(z3d main.cpp include/assets/data_stores/mesh_store.hpp include/assets/data_stores/point_cloud_store.hpp include/util/result.hpp - source/assets/file_parsers/mtl_loader.cpp + source/assets/file_parsers/mtl_parser.cpp include/util/line_parser.hpp include/assets/data_loaders/texture_loader.hpp source/assets/data_loaders/texture_loader.cpp @@ -247,6 +247,7 @@ add_executable(z3d main.cpp include/assets/data/pose_list_data.hpp include/assets/data_stores/pose_list_store.hpp include/assets/data_views/pose_list_view.hpp + include/util/vector_replace_range.hpp ) target_include_directories(z3d PRIVATE include) diff --git a/include/assets/components/mesh_vertex_components.hpp b/include/assets/components/mesh_vertex_components.hpp index 1f1fcdf..14b5e84 100755 --- a/include/assets/components/mesh_vertex_components.hpp +++ b/include/assets/components/mesh_vertex_components.hpp @@ -10,6 +10,8 @@ namespace assets::mesh_vertex_components using position = z3d::vec3; using normal = z3d::vec3; +using tangent = z3d::vec3; +using bi_tangent = z3d::vec3; using tex_coord = z3d::vec2; using color = z3d::vec3; using reflectance = z3d::f32; @@ -20,6 +22,8 @@ enum : z3d::size { position, normal, + tangent, + bi_tangent, tex_coord, color, reflectance @@ -31,6 +35,8 @@ enum class flags : z3d::u8 none = 0, position = 1 << indices::position, normal = 1 << indices::normal, + tangent = 1 << indices::tangent, + bi_tangent = 1 << indices::bi_tangent, tex_coord = 1 << indices::tex_coord, color = 1 << indices::color, reflectance = 1 << indices::reflectance diff --git a/include/assets/data/generic/component_set.hpp b/include/assets/data/generic/component_set.hpp index 4c4dbed..79082ce 100644 --- a/include/assets/data/generic/component_set.hpp +++ b/include/assets/data/generic/component_set.hpp @@ -4,16 +4,19 @@ namespace assets::detail { -template +template class component_set {}; -template -class component_set> +template +class component_set> { public: component_set() = default; + C component_flags{}; + z3d::structure> components{}; + protected: void clear_components() { @@ -25,8 +28,6 @@ protected: components ); } - - z3d::structure> components{}; }; } diff --git a/include/assets/data/material_data.hpp b/include/assets/data/material_data.hpp index ae4ddbc..0fba8b6 100755 --- a/include/assets/data/material_data.hpp +++ b/include/assets/data/material_data.hpp @@ -6,8 +6,10 @@ namespace assets { -struct material_data : detail::component_set -{ +struct material_data : public detail::component_set< + material_components::flags, + material_components::all +> { material_data() = default; @@ -16,9 +18,9 @@ struct material_data : detail::component_set [[nodiscard]] inline z3d::optional& specular_filter(); [[nodiscard]] inline z3d::optional& shininess(); [[nodiscard]] inline z3d::optional& alpha(); - [[nodiscard]] inline z3d::optional& specular_filter_texture_id(); - [[nodiscard]] inline z3d::optional& diffuse_filter_texture_id(); + [[nodiscard]] inline z3d::optional& ambient_filter_texture_id(); [[nodiscard]] inline z3d::optional& specular_filter_texture_id(); + [[nodiscard]] inline z3d::optional& diffuse_filter_texture_id(); [[nodiscard]] inline z3d::optional& shininess_texture_id(); [[nodiscard]] inline z3d::optional& alpha_texture_id(); [[nodiscard]] inline z3d::optional& bump_texture_id(); @@ -28,10 +30,9 @@ struct material_data : detail::component_set [[nodiscard]] inline const z3d::optional& specular_filter() const; [[nodiscard]] inline const z3d::optional& shininess() const; [[nodiscard]] inline const z3d::optional& alpha() const; - [[nodiscard]] inline const z3d::optional& transparency() const; - [[nodiscard]] inline const z3d::optional& specular_filter_texture_id() const; - [[nodiscard]] inline const z3d::optional& diffuse_filter_texture_id() const; + [[nodiscard]] inline const z3d::optional& ambient_filter_texture_id() const; [[nodiscard]] inline const z3d::optional& specular_filter_texture_id() const; + [[nodiscard]] inline const z3d::optional& diffuse_filter_texture_id() const; [[nodiscard]] inline const z3d::optional& shininess_texture_id() const; [[nodiscard]] inline const z3d::optional& alpha_texture_id() const; [[nodiscard]] inline const z3d::optional& bump_texture_id() const; diff --git a/include/assets/data/mesh_data.hpp b/include/assets/data/mesh_data.hpp index 05cbd13..36b8c36 100644 --- a/include/assets/data/mesh_data.hpp +++ b/include/assets/data/mesh_data.hpp @@ -7,7 +7,7 @@ namespace assets { -class mesh_data : detail::component_array_set< +class mesh_data : public detail::component_array_set< mesh_vertex_components::flags, mesh_vertex_components::all > { @@ -19,7 +19,7 @@ public: [[nodiscard]] inline z3d::vector& colors(); [[nodiscard]] inline z3d::vector& reflectances(); [[nodiscard]] inline z3d::vector& triangles(); - [[nodiscard]] inline auto& material(); + [[nodiscard]] inline material_id& material(); [[nodiscard]] inline const z3d::vector& positions() const; [[nodiscard]] inline const z3d::vector& normals() const; @@ -27,7 +27,7 @@ public: [[nodiscard]] inline const z3d::vector& colors() const; [[nodiscard]] inline const z3d::vector& reflectances() const; [[nodiscard]] inline const z3d::vector& triangles() const; - [[nodiscard]] inline const auto& material() const; + [[nodiscard]] inline const material_id& material() const; inline void clear(); diff --git a/include/assets/data/shader_source_data.hpp b/include/assets/data/shader_source_data.hpp index 40f3898..6573848 100644 --- a/include/assets/data/shader_source_data.hpp +++ b/include/assets/data/shader_source_data.hpp @@ -18,6 +18,8 @@ struct shader_source_data shader_components::flags components{}; shader_components::flags static_enable{}; shader_components::flags dynamic_enable{}; + + bool operator==(const metadata& meta) const = default; } meta; void clear() diff --git a/include/assets/data_loaders/material_library_loader.hpp b/include/assets/data_loaders/material_library_loader.hpp index 875628d..40c05a7 100644 --- a/include/assets/data_loaders/material_library_loader.hpp +++ b/include/assets/data_loaders/material_library_loader.hpp @@ -9,7 +9,7 @@ #include "util/string_list.hpp" -#include "assets/file_parsers/mtl_loader.hpp" +#include "assets/file_parsers/mtl_parser.hpp" // TODO not implemented?!? namespace assets @@ -17,7 +17,7 @@ namespace assets class material_library_loader : public base_dynamic_loader< material_components::flags, - mtl_loader + mtl_parser > { public: diff --git a/include/assets/data_stores/generic/generic_basic_store.hpp b/include/assets/data_stores/generic/generic_basic_store.hpp index 9cb547c..78bc2e4 100644 --- a/include/assets/data_stores/generic/generic_basic_store.hpp +++ b/include/assets/data_stores/generic/generic_basic_store.hpp @@ -1,38 +1,135 @@ #pragma once #include -#include +#include +#include -#include "util/uix.hpp" -#include "util/id_type.hpp" +namespace assets::detail { +template +class generic_basic_store; + + +template +class generic_basic_store_iterator +{ +public: + using size_type = std::size_t; + using id_type = ID; + using data_type = T; + using value_type = std::pair; + + using id_iterator_type = const id_type*; + using data_iterator_type = data_type*; + + using difference_type = std::ptrdiff_t; + using pointer = value_type*; + using reference = std::pair; + using iterator_category = std::random_access_iterator_tag; + +private: + friend generic_basic_store; + + generic_basic_store_iterator( + id_iterator_type ids, + data_iterator_type data, + std::size_t index + ); + +public: + constexpr generic_basic_store_iterator() noexcept = default; + + constexpr generic_basic_store_iterator(const generic_basic_store_iterator&) noexcept = default; + constexpr generic_basic_store_iterator(generic_basic_store_iterator&&) noexcept = default; + + constexpr generic_basic_store_iterator& operator=(const generic_basic_store_iterator&) noexcept = default; + constexpr generic_basic_store_iterator& operator=(generic_basic_store_iterator&&) noexcept = default; + + reference operator*() const; + + generic_basic_store_iterator& operator++(); + generic_basic_store_iterator operator++(int); + generic_basic_store_iterator& operator--(); + generic_basic_store_iterator operator--(int); + + generic_basic_store_iterator& operator+=(difference_type n); + generic_basic_store_iterator& operator-=(difference_type n); + generic_basic_store_iterator operator+(difference_type n) const; + generic_basic_store_iterator operator-(difference_type n) const; + difference_type operator-(const generic_basic_store_iterator& other) const; + + reference operator[](difference_type n) const; + + bool operator==(const generic_basic_store_iterator& other) const; + bool operator!=(const generic_basic_store_iterator& other) const; + bool operator<(const generic_basic_store_iterator& other) const; + bool operator<=(const generic_basic_store_iterator& other) const; + bool operator>(const generic_basic_store_iterator& other) const; + bool operator>=(const generic_basic_store_iterator& other) const; + +protected: + reference dereference() const; + +private: + id_iterator_type m_ids{}; + data_iterator_type m_data{}; + size_type m_index{}; +}; template class generic_basic_store { public: + using id_type = ID; using container_type = std::vector; - using iterator_type = typename container_type::iterator; - using const_iterator = typename container_type::const_iterator; + using iterator = generic_basic_store_iterator; + using const_iterator = generic_basic_store_iterator...>; - ID add(const T& data); + using size_type = std::size_t; + using data_type = T; - [[nodiscard]] std::pair find(ID id); + bool insert(ID id, const T& data); - [[nodiscard]] std::pair find(ID id) const; + bool insert(iterator it, id_type id, const data_type& data); - [[nodiscard]] std::span data(); + [[nodiscard]] std::pair find(id_type id); - [[nodiscard]] std::span data() const; + [[nodiscard]] std::pair find(id_type id) const; - void remove(iterator_type it); + void remove(iterator it); void clear(); + [[nodiscard]] inline std::shared_lock acquire_read_lock() const; + + [[nodiscard]] inline std::unique_lock acquire_write_lock(); + + iterator begin(); + + iterator end(); + + const_iterator begin() const; + + const_iterator end() const; + + const_iterator cbegin() const; + + const_iterator cend() const; + +protected: + bool unsafe_insert(iterator it, ID id, const T& data); + + [[nodiscard]] std::pair unsafe_find(ID id); + + [[nodiscard]] std::pair unsafe_find(ID id) const; + private: - std::vector m_data; std::vector m_ids; + std::vector m_data; + mutable std::shared_mutex m_mutex; }; +} + #define INCLUDE_GENERIC_BASIC_STORE_IMPLEMENTATION #include "assets/data_stores/generic/generic_basic_store.ipp" #undef INCLUDE_GENERIC_BASIC_STORE_IMPLEMENTATION diff --git a/include/assets/data_stores/generic/generic_material_store.hpp b/include/assets/data_stores/generic/generic_material_store.hpp index d8ae0c2..af036b6 100644 --- a/include/assets/data_stores/generic/generic_material_store.hpp +++ b/include/assets/data_stores/generic/generic_material_store.hpp @@ -3,12 +3,13 @@ #include "assets/components/material_components.hpp" #include "assets/data/material_data.hpp" #include "assets/data_views/material_view.hpp" - +#include +#include namespace assets::detail { -template +template class generic_material_store; template @@ -33,7 +34,7 @@ public: using iterator_category = std::random_access_iterator_tag; private: - friend generic_material_store; + friend generic_material_store>; generic_material_store_iterator( id_iterator_type ids, @@ -94,32 +95,37 @@ private: template -class generic_material_store +class generic_material_store> { public: using size_type = std::size_t; using count_type = ztu::u32; using component_flag_type = material_components::flags; + using data_type = material_data; - using iterator_type = generic_material_store_iterator; + using iterator = generic_material_store_iterator; using const_iterator = generic_material_store_iterator...>; - using view_type = std::ranges::subrange; - using const_view_type = std::ranges::subrange; using id_type = material_id; - id_type add(const material_data& material); + bool insert(id_type id, const data_type& data); - [[nodiscard]] std::pair find(id_type id); + bool insert(iterator it, id_type id, const data_type& data); + + [[nodiscard]] std::pair find(id_type id); [[nodiscard]] std::pair find(id_type id) const; - void remove(const iterator_type& it); + void remove(const iterator& it); void clear(); - iterator_type begin(); + [[nodiscard]] inline std::shared_lock acquire_read_lock() const; - iterator_type end(); + [[nodiscard]] inline std::unique_lock acquire_write_lock(); + + iterator begin(); + + iterator end(); const_iterator begin() const; @@ -129,11 +135,13 @@ public: const_iterator cend() const; - view_type view(); - - const_view_type view() const; - protected: + bool unsafe_insert(iterator it, id_type id, const data_type& data); + + [[nodiscard]] std::pair unsafe_find(id_type id); + + [[nodiscard]] std::pair unsafe_find(id_type id) const; + std::tuple...> component_iterators(); std::tuple>...> component_iterators() const; @@ -144,6 +152,7 @@ private: std::vector m_ids; std::tuple...> m_component_arrays; std::vector m_component_flag_counts; + mutable std::shared_mutex m_mutex; }; } diff --git a/include/assets/data_stores/generic/generic_mesh_store.hpp b/include/assets/data_stores/generic/generic_mesh_store.hpp index 84f08ba..257aafd 100644 --- a/include/assets/data_stores/generic/generic_mesh_store.hpp +++ b/include/assets/data_stores/generic/generic_mesh_store.hpp @@ -1,5 +1,8 @@ #pragma once +#include +#include + #include "assets/components/mesh_vertex_components.hpp" #include "assets/data_stores/material_store.hpp" #include "assets/data/mesh_data.hpp" @@ -8,7 +11,7 @@ namespace assets::detail { -template +template class generic_mesh_store; template @@ -17,7 +20,7 @@ class generic_mesh_store_iterator public: using size_type = std::size_t; using count_type = ztu::u32; - using index_type = z3d::vertex_index; + using triangle_type = z3d::index_triangle; using material_id_type = material_store::id_type; using component_flag_type = mesh_vertex_components::flags; using id_type = mesh_id; @@ -26,7 +29,7 @@ public: using id_iterator_type = id_type*; using component_iterator_type = std::tuple...>; - using index_iterator_type = index_type*; + using triangle_iterator_type = triangle_type*; using flag_count_iterator_type = const flag_count_type*; using material_id_iterator_type = material_id_type*; @@ -37,11 +40,11 @@ public: using iterator_category = std::random_access_iterator_tag; private: - friend generic_mesh_store; + friend generic_mesh_store>; generic_mesh_store_iterator( id_iterator_type ids, - index_iterator_type indices, + triangle_iterator_type triangles, const component_iterator_type& components, material_id_iterator_type material_ids, flag_count_iterator_type flag_counts, @@ -92,7 +95,7 @@ protected: private: id_iterator_type m_ids{}; - index_iterator_type m_indices{}; + triangle_iterator_type m_triangles{}; component_iterator_type m_components{}; material_id_iterator_type m_material_ids{}; flag_count_iterator_type m_flag_counts{}; @@ -102,34 +105,39 @@ private: template -class generic_mesh_store +class generic_mesh_store> { public: using size_type = std::size_t; using count_type = ztu::u32; - using index_type = z3d::vertex_index; + using triangle_type = z3d::index_triangle; using component_flag_type = mesh_vertex_components::flags; - using material_id_type = material_store::id_type; - - using iterator_type = generic_mesh_store_iterator; - using const_iterator = generic_mesh_store_iterator...>; - using view_type = std::ranges::subrange; - using const_view_type = std::ranges::subrange; + using material_id_type = material_id; + using data_type = mesh_data; using id_type = mesh_id; - id_type add(const mesh_data& mesh); + using iterator = generic_mesh_store_iterator; + using const_iterator = generic_mesh_store_iterator...>; - [[nodiscard]] std::pair find(id_type id); + bool insert(id_type id, const data_type& data); + + bool insert(iterator it, id_type id, const data_type& data); + + [[nodiscard]] std::pair find(id_type id); [[nodiscard]] std::pair find(id_type id) const; - void remove(const iterator_type& it); + void remove(const iterator& it); void clear(); - iterator_type begin(); + [[nodiscard]] inline std::shared_lock acquire_read_lock() const; - iterator_type end(); + [[nodiscard]] inline std::unique_lock acquire_write_lock(); + + iterator begin(); + + iterator end(); const_iterator begin() const; @@ -139,11 +147,12 @@ public: const_iterator cend() const; - view_type view(); - - const_view_type view() const; - protected: + bool unsafe_insert(iterator it, id_type id, const data_type& data); + + [[nodiscard]] std::pair unsafe_find(id_type id); + + [[nodiscard]] std::pair unsafe_find(id_type id) const; std::tuple...> component_iterators(); std::tuple>...> component_iterators() const; @@ -152,11 +161,11 @@ protected: private: std::vector m_ids; - std::vector m_indices; - std::tuple...> m_component_arrays; + std::vector m_triangles; std::vector> m_component_flag_counts; + std::tuple...> m_component_arrays; std::vector m_material_ids; - id_type m_next_data_id{ 1 }; + mutable std::shared_mutex m_mutex{}; }; } diff --git a/include/assets/data_stores/generic/generic_point_cloud_store.hpp b/include/assets/data_stores/generic/generic_point_cloud_store.hpp index 7531f0a..5d35b02 100644 --- a/include/assets/data_stores/generic/generic_point_cloud_store.hpp +++ b/include/assets/data_stores/generic/generic_point_cloud_store.hpp @@ -1,19 +1,19 @@ #pragma once +#include +#include #include "util/uix.hpp" #include "util/id_type.hpp" #include "assets/components/point_cloud_vertex_components.hpp" #include "assets/data/point_cloud_data.hpp" #include "assets/data_views/point_cloud_view.hpp" -namespace assets +namespace assets::detail { -template +template class generic_point_cloud_store; -namespace detail -{ template class generic_point_cloud_store_iterator @@ -37,13 +37,13 @@ public: using iterator_category = std::random_access_iterator_tag; private: - friend generic_point_cloud_store; + friend generic_point_cloud_store>; generic_point_cloud_store_iterator( id_iterator_type ids, const component_iterator_type& components, flag_count_iterator_type flag_counts, - std::size_t index, + size_type index, const offsets_type& offsets ); @@ -98,31 +98,37 @@ private: template -class generic_point_cloud_store +class generic_point_cloud_store> { public: using size_type = std::size_t; using count_type = ztu::u32; using component_flag_type = point_cloud_vertex_components::flags; - - using data_type = point_cloud_data; - using iterator_type = generic_point_cloud_store_iterator; - using const_iterator = generic_point_cloud_store_iterator...>; using id_type = point_cloud_id; + using data_type = point_cloud_data; - id_type add(id_type id, const data_type& point_cloud); + using iterator = generic_point_cloud_store_iterator; + using const_iterator = generic_point_cloud_store_iterator...>; - [[nodiscard]] std::pair find(id_type id); + bool insert(id_type id, const data_type& data); + + bool insert(iterator it, id_type id, const data_type& data); + + [[nodiscard]] std::pair find(id_type id); [[nodiscard]] std::pair find(id_type id) const; - void remove(const iterator_type& it); + void remove(const iterator& it); void clear(); - iterator_type begin(); + [[nodiscard]] inline std::shared_lock acquire_read_lock() const; - iterator_type end(); + [[nodiscard]] inline std::unique_lock acquire_write_lock(); + + iterator begin(); + + iterator end(); const_iterator begin() const; @@ -133,6 +139,12 @@ public: const_iterator cend() const; protected: + bool unsafe_insert(iterator it, id_type id, const data_type& data); + + [[nodiscard]] std::pair unsafe_find(id_type id); + + [[nodiscard]] std::pair unsafe_find(id_type id) const; + std::tuple...> component_iterators(); std::tuple>...> component_iterators() const; @@ -143,12 +155,11 @@ private: std::vector m_ids; std::tuple...> m_component_arrays; std::vector> m_component_flag_counts; - id_type m_next_data_id{ 1 }; + mutable std::shared_mutex m_mutex; }; } -} #define INCLUDE_GENERIC_POINT_CLOUD_STORE_IMPLEMENTATION diff --git a/include/assets/data_stores/material_library_store.hpp b/include/assets/data_stores/material_library_store.hpp index 7886024..f01f2ec 100644 --- a/include/assets/data_stores/material_library_store.hpp +++ b/include/assets/data_stores/material_library_store.hpp @@ -1,11 +1,12 @@ #pragma once #include "generic/generic_basic_store.hpp" +#include "assets/identifiers.hpp" #include "assets/data/material_library_data.hpp" namespace assets { -using material_library_store = generic_basic_store; +using material_library_store = detail::generic_basic_store; } diff --git a/include/assets/data_stores/material_store.hpp b/include/assets/data_stores/material_store.hpp index 608ce51..42d5dfa 100644 --- a/include/assets/data_stores/material_store.hpp +++ b/include/assets/data_stores/material_store.hpp @@ -5,15 +5,6 @@ namespace assets { -using material_store = detail::generic_material_store< - material_components::surface_properties, - material_components::alpha, - texture_store::id_type, - texture_store::id_type, - texture_store::id_type, - texture_store::id_type, - texture_store::id_type, - texture_store::id_type ->; +using material_store = detail::generic_material_store; } diff --git a/include/assets/data_stores/mesh_store.hpp b/include/assets/data_stores/mesh_store.hpp index aba7524..f4583d4 100644 --- a/include/assets/data_stores/mesh_store.hpp +++ b/include/assets/data_stores/mesh_store.hpp @@ -6,11 +6,7 @@ namespace assets { using mesh_store = detail::generic_mesh_store< - mesh_vertex_components::position, - mesh_vertex_components::normal, - mesh_vertex_components::tex_coord, - mesh_vertex_components::color, - mesh_vertex_components::reflectance + mesh_vertex_components::all >; } diff --git a/include/assets/data_stores/point_cloud_store.hpp b/include/assets/data_stores/point_cloud_store.hpp index 6b76a80..179d4fa 100644 --- a/include/assets/data_stores/point_cloud_store.hpp +++ b/include/assets/data_stores/point_cloud_store.hpp @@ -8,10 +8,7 @@ namespace assets { using point_cloud_store = detail::generic_point_cloud_store< - point_cloud_vertex_components::position, - point_cloud_vertex_components::normal, - point_cloud_vertex_components::color, - point_cloud_vertex_components::reflectance + point_cloud_vertex_components::all >; } diff --git a/include/assets/data_stores/pose_list_store.hpp b/include/assets/data_stores/pose_list_store.hpp index 402d6e5..0e91991 100644 --- a/include/assets/data_stores/pose_list_store.hpp +++ b/include/assets/data_stores/pose_list_store.hpp @@ -1,6 +1,8 @@ #pragma once -#include "generic/generic_basic_store.hpp" +#include +#include + #include "assets/identifiers.hpp" #include "assets/data/pose_list_data.hpp" #include "assets/data_views/pose_list_view.hpp" @@ -75,7 +77,7 @@ protected: void calc_offset(difference_type n); - reference dereference() const; + [[nodiscard]] reference dereference() const; private: id_iterator_type m_ids{}; @@ -92,28 +94,30 @@ public: using size_type = std::size_t; using count_type = ztu::u32; - using iterator_type = pose_list_store_iterator; + using iterator = pose_list_store_iterator; using const_iterator = pose_list_store_iterator; using data_type = pose_list_data; using id_type = pose_list_id; - // TODO not storing metadata - inline id_type add( - id_type id, - const data_type& pose_list - ); + bool insert(id_type id, const data_type& data); - [[nodiscard]] inline std::pair find(id_type id); + bool insert(iterator it, id_type id, const data_type& data); - [[nodiscard]] inline std::pair find(id_type id) const; + [[nodiscard]] std::pair find(id_type id); - inline void remove(const iterator_type& it); + [[nodiscard]] std::pair find(id_type id) const; + + inline void remove(const iterator& it); inline void clear(); - [[nodiscard]] inline iterator_type begin(); + [[nodiscard]] inline std::shared_lock acquire_read_lock() const; - [[nodiscard]] inline iterator_type end(); + [[nodiscard]] inline std::unique_lock acquire_write_lock(); + + [[nodiscard]] inline iterator begin(); + + [[nodiscard]] inline iterator end(); [[nodiscard]] inline const_iterator begin() const; @@ -123,11 +127,18 @@ public: [[nodiscard]] inline const_iterator cend() const; +protected: + bool unsafe_insert(iterator it, id_type id, const data_type& data); + + [[nodiscard]] std::pair unsafe_find(id_type id); + + [[nodiscard]] std::pair unsafe_find(id_type id) const; private: std::vector m_ids; std::vector m_poses; std::vector m_lengths; + mutable std::shared_mutex m_mutex; }; } diff --git a/include/assets/data_stores/pose_store.hpp b/include/assets/data_stores/pose_store.hpp index 804db17..2fbb009 100644 --- a/include/assets/data_stores/pose_store.hpp +++ b/include/assets/data_stores/pose_store.hpp @@ -1,11 +1,12 @@ #pragma once #include "generic/generic_basic_store.hpp" +#include "assets/identifiers.hpp" #include "assets/data/pose_data.hpp" namespace assets { -using pose_store = generic_basic_store; +using pose_store = detail::generic_basic_store; } diff --git a/include/assets/data_stores/shader_source_store.hpp b/include/assets/data_stores/shader_source_store.hpp index d944298..507c7ca 100644 --- a/include/assets/data_stores/shader_source_store.hpp +++ b/include/assets/data_stores/shader_source_store.hpp @@ -1,6 +1,7 @@ #pragma once -#include "generic/generic_basic_store.hpp" +#include +#include #include "assets/data/shader_source_data.hpp" #include "assets/data_views/shader_source_view.hpp" @@ -95,29 +96,33 @@ public: using size_type = std::size_t; using count_type = ztu::u32; - using iterator_type = shader_source_store_iterator; + using iterator = shader_source_store_iterator; using const_iterator = shader_source_store_iterator; - using view_type = std::ranges::subrange; + using view_type = std::ranges::subrange; using const_view_type = std::ranges::subrange; using id_type = shader_source_id; + using data_type = shader_source_data; - // TODO not storing metadata - inline id_type add( - shader_source_id id, - const shader_source_data& shader_source - ); + bool insert(id_type id, const data_type& data); - [[nodiscard]] inline std::pair find(id_type id); + bool insert(iterator it, id_type id, const data_type& data); - [[nodiscard]] inline std::pair find(id_type id) const; + [[nodiscard]] std::pair find(id_type id); - inline void remove(const iterator_type& it); + [[nodiscard]] std::pair find(id_type id) const; + + + inline void remove(const iterator& it); inline void clear(); - [[nodiscard]] inline iterator_type begin(); + [[nodiscard]] inline std::shared_lock acquire_read_lock() const; - [[nodiscard]] inline iterator_type end(); + [[nodiscard]] inline std::unique_lock acquire_write_lock(); + + [[nodiscard]] inline iterator begin(); + + [[nodiscard]] inline iterator end(); [[nodiscard]] inline const_iterator begin() const; @@ -127,12 +132,19 @@ public: [[nodiscard]] inline const_iterator cend() const; +protected: + bool unsafe_insert(iterator it, id_type id, const data_type& data); + + [[nodiscard]] std::pair unsafe_find(id_type id); + + [[nodiscard]] std::pair unsafe_find(id_type id) const; private: std::vector m_ids; std::vector m_strings; std::vector m_lengths; std::vector m_metadata; + mutable std::shared_mutex m_mutex; }; } diff --git a/include/assets/data_stores/texture_store.hpp b/include/assets/data_stores/texture_store.hpp index f29dc9f..0b74438 100644 --- a/include/assets/data_stores/texture_store.hpp +++ b/include/assets/data_stores/texture_store.hpp @@ -1,12 +1,13 @@ #pragma once #include "generic/generic_basic_store.hpp" +#include "assets/identifiers.hpp" #include "assets/data/texture_data.hpp" namespace assets { -using texture_store = generic_basic_store; +using texture_store = detail::generic_basic_store; } diff --git a/include/assets/data_views/shader_source_view.hpp b/include/assets/data_views/shader_source_view.hpp index fa112d1..d82a61d 100644 --- a/include/assets/data_views/shader_source_view.hpp +++ b/include/assets/data_views/shader_source_view.hpp @@ -1,8 +1,7 @@ #pragma once #include -#include "assets/model_geometry.hpp" -#include "assets/components/shader_components.hpp" +#include "assets/data/shader_source_data.hpp" namespace assets { @@ -10,11 +9,7 @@ namespace assets struct shader_source_view { std::string_view source; - model_geometry::types geometry_type; - shader_components::stage stage; - shader_components::flags components{}; - shader_components::flags static_enable{}; - shader_components::flags dynamic_enable{}; + shader_source_data::metadata meta; }; } diff --git a/include/assets/file_parsers/mtl_loader.hpp b/include/assets/file_parsers/mtl_loader.hpp deleted file mode 100644 index 5a3b644..0000000 --- a/include/assets/file_parsers/mtl_loader.hpp +++ /dev/null @@ -1,60 +0,0 @@ -#pragma once - -#include -#include - -#include "assets/prefetch_lookup.hpp" -#include "assets/prefetch_queue.hpp" -#include "assets/data/material_data.hpp" -#include "assets/data/material_library_data.hpp" -#include "assets/data_stores/material_store.hpp" -#include "assets/data_stores/material_library_store.hpp" -#include "util/result.hpp" - -namespace assets -{ - -namespace mtl_loader_error -{ -enum class codes { - ok = 0, - cannot_open_file, - cannot_open_texture, - malformed_ambient_color, - malformed_diffuse_color, - malformed_specular_color, - malformed_specular_exponent, - malformed_dissolve, - unknown_line_begin -}; -} // namespace mtl_loader_error - -struct mtl_loader -{ - static constexpr auto name = std::string_view("mtl"); - - [[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, - shader_source_store& store, - bool pedantic = false - ); - -protected: - static void find_textures( - std::span buffer, - std::filesystem::path& path_buffer, - const std::filesystem::path& base_directory, - std::ifstream& in, - ztu::string_list& texture_filenames - ); -}; - -} diff --git a/include/assets/file_parsers/mtl_parser.hpp b/include/assets/file_parsers/mtl_parser.hpp new file mode 100644 index 0000000..0c50ffb --- /dev/null +++ b/include/assets/file_parsers/mtl_parser.hpp @@ -0,0 +1,96 @@ +#pragma once + +#include +#include + +#include "assets/data_stores.hpp" +#include "assets/path_id_lookups.hpp" +#include "assets/prefetch_lookup.hpp" +#include "assets/prefetch_queue.hpp" +#include "assets/data/material_data.hpp" +#include "assets/data/material_library_data.hpp" +#include "assets/data_stores/material_store.hpp" +#include "assets/data_stores/material_library_store.hpp" +#include "util/result.hpp" + +namespace assets +{ + +namespace mtl_parser_error +{ +enum class codes { + ok = 0, + cannot_open_file, + // TODO these are incomplete + cannot_open_texture, + malformed_ambient_color, + malformed_diffuse_color, + malformed_specular_color, + malformed_specular_exponent, + malformed_dissolve, + unknown_line_begin +}; +} // namespace mtl_loader_error + +struct mtl_parser +{ + static constexpr auto name = std::string_view("mtl"); + using data_type = material_library_data; + using store_type = material_library_store; + using lookup_type = material_library_id_lookup; + + [[nodiscard]] std::error_code prefetch( + path_id_lookups& lookups + ); + + [[nodiscard]] std::error_code load( + path_id_lookups& lookups, + data_stores& stores, + bool pedantic = false + ); + +protected: + class parser_context + { + public: + parser_context( + const texture_id_lookup& texture_id_lookup, + material_id_lookup& material_id_lookup, + material_store& material_store, + store_type& store, + std::mutex& store_mutex + ); + + void operator()(lookup_type::const_pointer entry) noexcept; + + protected: + void reset(); + + [[nodiscard]] std::optional fetch_texture_id( + const std::filesystem::path& mtl_dir, + std::string_view filename, + std::string_view texture_type_name + ); + + private: + const texture_id_lookup* m_texture_id_lookup; + material_id_lookup* m_material_id_lookup; + material_store* m_material_store; + store_type* m_store; + std::mutex* m_store_mutex; + data_type m_buffer{}; + }; + + static void find_textures( + std::span buffer, + std::filesystem::path& path_buffer, + const std::filesystem::path& base_directory, + std::ifstream& in, + ztu::string_list& texture_filenames + ); + +private: + std::vector m_path_buffer; +}; + +} diff --git a/include/opengl/data_managers/mesh_index_buffer_manager.hpp b/include/opengl/data_managers/mesh_index_buffer_manager.hpp index 9a7dc91..9507277 100644 --- a/include/opengl/data_managers/mesh_index_buffer_manager.hpp +++ b/include/opengl/data_managers/mesh_index_buffer_manager.hpp @@ -30,7 +30,7 @@ protected: resource_manager_type m_resource_manager; private: - std::vector m_mesh_buffer; + std::vector m_mesh_buffer; std::vector m_buffer_id_buffer; }; } diff --git a/include/opengl/data_managers/mesh_vertex_buffer_manager.hpp b/include/opengl/data_managers/mesh_vertex_buffer_manager.hpp index 64e4523..da11186 100644 --- a/include/opengl/data_managers/mesh_vertex_buffer_manager.hpp +++ b/include/opengl/data_managers/mesh_vertex_buffer_manager.hpp @@ -31,7 +31,7 @@ protected: resource_manager_type m_resource_manager; private: - std::vector m_mesh_buffer; + std::vector m_mesh_buffer; std::vector m_buffer_id_buffer; std::vector m_byte_buffer; diff --git a/include/opengl/data_managers/point_cloud_vertex_buffer_manager.hpp b/include/opengl/data_managers/point_cloud_vertex_buffer_manager.hpp index 71fcac7..fd4bf10 100644 --- a/include/opengl/data_managers/point_cloud_vertex_buffer_manager.hpp +++ b/include/opengl/data_managers/point_cloud_vertex_buffer_manager.hpp @@ -31,7 +31,7 @@ protected: resource_manager_type m_resource_manager; private: - std::vector m_point_cloud_buffer; + std::vector m_point_cloud_buffer; std::vector m_buffer_id_buffer; std::vector m_byte_buffer; }; diff --git a/include/opengl/metadata/shader_source_metadata.hpp b/include/opengl/metadata/shader_source_metadata.hpp index 6ec2d11..d8874e5 100644 --- a/include/opengl/metadata/shader_source_metadata.hpp +++ b/include/opengl/metadata/shader_source_metadata.hpp @@ -1,18 +1,10 @@ #pragma once -#include "assets/model_geometry.hpp" -#include "assets/components/shader_components.hpp" +#include "assets/data/shader_source_data.hpp" namespace zgl { -struct shader_source_metadata -{ - assets::model_geometry::types geometry_type; - assets::shader_components::stage stage; - assets::shader_components::flags components{}; - assets::shader_components::flags static_enable{}; - assets::shader_components::flags dynamic_enable{}; -}; +using shader_source_metadata = assets::shader_source_data::metadata; } diff --git a/include/util/file_id_lookup.hpp b/include/util/file_id_lookup.hpp index f004799..c25bde5 100644 --- a/include/util/file_id_lookup.hpp +++ b/include/util/file_id_lookup.hpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include template class file_id_lookup @@ -29,64 +31,107 @@ public: using node_type = typename container_type::node_type; using insert_return_type = typename container_type::insert_return_type; + + std::pair try_emplace(const key_type& path) + { + std::unique_lock lock(m_mutex); + auto it = m_container.find(path); + const auto is_new = it == m_container.end(); + if (is_new) { + it = m_container.emplace_hint(it, path, ID::next()); + } + return { it, is_new }; + } + + [[nodiscard]] bool empty() const noexcept + { + std::shared_lock lock(m_mutex); + return m_container.empty(); + } + [[nodiscard]] size_type size() const noexcept + { + std::shared_lock lock(m_mutex); + return m_container.size(); + } + [[nodiscard]] size_type max_size() const noexcept + { + std::shared_lock lock(m_mutex); + return m_container.max_size(); + } + + void by_extension(const std::string_view extension, std::vector& dst) const + { + std::shared_lock lock(m_mutex); + std::ranges::copy( + m_container | + std::views::filter([ + &](const value_type& entry) { + return entry.first.extension() == extension; + } + ) | + std::views::transform([ + &](const value_type& entry) { + return &entry; + } + ), + std::back_inserter(dst) + ); + } + + + [[nodiscard]] bool contains(const key_type& key) const + { + std::shared_lock lock(m_mutex); + return m_container.contains(key); + } + [[nodiscard]] size_type count(const key_type& key) const + { + std::shared_lock lock(m_mutex); + return m_container.count(key); + } + [[nodiscard]] iterator find(const key_type& key) + { + std::shared_lock lock(m_mutex); + return m_container.find(key); + } + [[nodiscard]] const_iterator find(const key_type& key) const + { + std::shared_lock lock(m_mutex); + return m_container.find(key); + } + + iterator erase(iterator pos) + { + std::unique_lock lock(m_mutex); + return m_container.erase(pos); + } + iterator erase(const_iterator pos) + { + std::unique_lock lock(m_mutex); + return m_container.erase(pos); + } + iterator erase(const_iterator first, const_iterator last) + { + std::unique_lock lock(m_mutex); + return m_container.erase(first, last); + } + size_type erase(const key_type& key) + { + std::unique_lock lock(m_mutex); + return m_container.erase(key); + } + void clear() noexcept + { + std::unique_lock lock(m_mutex); + m_container.clear(); + } + [[nodiscard]] iterator begin() noexcept { return m_container.begin(); } [[nodiscard]] const_iterator begin() const noexcept { return m_container.begin(); } [[nodiscard]] const_iterator cbegin() const noexcept { return m_container.cbegin(); } [[nodiscard]] iterator end() noexcept { return m_container.end(); } [[nodiscard]] const_iterator end() const noexcept { return m_container.end(); } [[nodiscard]] const_iterator cend() const noexcept { return m_container.cend(); } - [[nodiscard]] bool empty() const noexcept { return m_container.empty(); } - [[nodiscard]] size_type size() const noexcept { return m_container.size(); } - [[nodiscard]] size_type max_size() const noexcept { return m_container.max_size(); } - - void by_extension( - const std::string_view extension, - std::vector& dst - ) const { - std::ranges::copy( - m_container | - std::views::filter( - [&](const value_type& entry) - { - return entry.first.extension() == extension; - } - ) | - std::views::transform( - [&](const value_type& entry) - { - return &entry; - } - ), - std::back_inserter(dst) - ); - } - - - std::pair try_emplace(const key_type& path) - { - auto it = m_container.find(path); - - const auto is_new = it == m_container.end(); - - if (not is_new) - { - it = m_container.emplace_hint(it, path, ID::next()); - } - - return { it, is_new }; - } - - [[nodiscard]] bool contains(const key_type& key) const { return m_container.contains(key); } - [[nodiscard]] size_type count(const key_type& key) const { return m_container.count(key); } - [[nodiscard]] iterator find(const key_type& key) { return m_container.find(key); } - [[nodiscard]] const_iterator find(const key_type& key) const { return m_container.find(key); } - - iterator erase(iterator pos) { return m_container.erase(pos); } - iterator erase(const_iterator pos) { return m_container.erase(pos); } - iterator erase(const_iterator first, const_iterator last) { return m_container.erase(first, last); } - size_type erase(const key_type& key) { return m_container.erase(key); } - void clear() noexcept { m_container.clear(); } - private: @@ -101,4 +146,5 @@ private: } container_type m_container; + std::shared_mutex m_mutex; }; \ No newline at end of file diff --git a/include/util/vector_replace_range.hpp b/include/util/vector_replace_range.hpp new file mode 100644 index 0000000..dad7e59 --- /dev/null +++ b/include/util/vector_replace_range.hpp @@ -0,0 +1,33 @@ +#pragma once + + +#include +#include + +namespace ztu +{ + +template +void replace_range( + std::vector& dst, + typename std::vector::iterator dst_begin, + typename std::vector::iterator dst_end, + InputIt src_begin, + InputIt src_end +) { + const auto dst_size = std::distance(dst_begin, dst_end); + const auto src_size = std::distance(src_begin, src_end); + + if (dst_size < src_size) + { + dst.insert(dst_end, src_begin + dst_size, src_end); + } + else if (dst_size > src_size) + { + dst.erase(dst_begin + src_size, dst_end); + } + + std::copy_n(src_begin, std::min(src_size, dst_size), dst_begin); +} + +} diff --git a/source/assets/data/material_data.ipp b/source/assets/data/material_data.ipp index bb1276e..00ca2cb 100644 --- a/source/assets/data/material_data.ipp +++ b/source/assets/data/material_data.ipp @@ -2,17 +2,17 @@ # error Never include this file directly include 'material_data.hpp' #endif -inline std::optional& assets::material_data::specular_filter() +inline std::optional& assets::material_data::specular_filter() { - return std::get(components); + return std::get(components); } inline std::optional& assets::material_data::diffuse_filter() { return std::get(components); } -inline std::optional& assets::material_data::specular_filter() +inline std::optional& assets::material_data::ambient_filter() { - return std::get(components); + return std::get(components); } inline std::optional& assets::material_data::shininess() { @@ -23,17 +23,17 @@ inline std::optional& assets::material_data: return std::get(components); } -inline std::optional& assets::material_data::specular_filter_texture_id() +inline std::optional& assets::material_data::specular_filter_texture_id() { - return std::get(components); + return std::get(components); } inline std::optional& assets::material_data::diffuse_filter_texture_id() { return std::get(components); } -inline std::optional& assets::material_data::specular_filter_texture_id() +inline std::optional& assets::material_data::ambient_filter_texture_id() { - return std::get(components); + return std::get(components); } inline std::optional& assets::material_data::shininess_texture_id() { @@ -48,17 +48,17 @@ inline std::optional& assets::materia return std::get& assets::material_data::specular_filter() const +inline const std::optional& assets::material_data::specular_filter() const { - return std::get(components); + return std::get(components); } inline const std::optional& assets::material_data::diffuse_filter() const { return std::get(components); } -inline const std::optional& assets::material_data::specular_filter() const +inline const std::optional& assets::material_data::ambient_filter() const { - return std::get(components); + return std::get(components); } inline const std::optional& assets::material_data::shininess() const { @@ -69,9 +69,9 @@ inline const std::optional& assets::material return std::get(components); } -inline const std::optional& assets::material_data::specular_filter_texture_id() const +inline const std::optional& assets::material_data::specular_filter_texture_id() const { - return std::get(components); + return std::get(components); } inline const std::optional& assets::material_data::diffuse_filter_texture_id() const @@ -79,9 +79,9 @@ inline const std::optional& return std::get(components); } -inline const std::optional& assets::material_data::specular_filter_texture_id() const +inline const std::optional& assets::material_data::ambient_filter_texture_id() const { - return std::get(components); + return std::get(components); } inline const std::optional& assets::material_data::shininess_texture_id() const diff --git a/source/assets/data_stores/generic/generic_basic_store.ipp b/source/assets/data_stores/generic/generic_basic_store.ipp index f28b5cd..fd275dd 100644 --- a/source/assets/data_stores/generic/generic_basic_store.ipp +++ b/source/assets/data_stores/generic/generic_basic_store.ipp @@ -3,61 +3,288 @@ #endif #include +#include -template -typename generic_basic_store::id_type generic_basic_store::add(const T& data) -{ - auto id = id_type{ m_next_data_id.index++ }; - m_data.emplace_back(data); - m_ids.emplace_back(id); - return id; + +template +assets::detail::generic_basic_store_iterator::generic_basic_store_iterator( + id_iterator_type ids, + data_iterator_type data, + const size_type index +) : + m_ids{ ids }, + m_data{ data }, + m_index{ index } {} + + +template +typename assets::detail::generic_basic_store_iterator::reference assets::detail::generic_basic_store_iterator::operator*() const { + return dereference(); } -template -std::pair::iterator_type, bool> generic_basic_store::find(id_type id) -{ - const auto it = std::ranges::upper_bound(m_ids, id); - - const auto found = it != m_ids.begin() and *std::prev(it) == id; - const auto index = it - m_ids.begin() - found; - - return { m_data.begin() + index, found }; +template +assets::detail::generic_basic_store_iterator& assets::detail::generic_basic_store_iterator::operator++() { + ++m_index; + return *this; } -template -std::pair::const_iterator, bool> generic_basic_store::find(id_type id) const -{ - const auto it = std::ranges::upper_bound(m_ids, id); - - const auto found = it != m_ids.begin() and *std::prev(it) == id; - const auto index = it - m_ids.begin() - found; - - return { m_data.begin() + index, found }; +template +assets::detail::generic_basic_store_iterator assets::detail::generic_basic_store_iterator::operator++(int) { + generic_basic_store_iterator tmp = *this; + ++(*this); + return tmp; } -template -void generic_basic_store::remove(iterator_type it) +template +assets::detail::generic_basic_store_iterator& assets::detail::generic_basic_store_iterator::operator--() { + --m_index; + return *this; +} + +template +assets::detail::generic_basic_store_iterator assets::detail::generic_basic_store_iterator::operator--(int) { + auto tmp = *this; + --(*this); + return tmp; +} + +template +assets::detail::generic_basic_store_iterator& assets::detail::generic_basic_store_iterator::operator+=(const difference_type n) { - const auto index = it - m_data.begin(); - m_data.erase(it); + m_index += n; + return *this; +} + +template +assets::detail::generic_basic_store_iterator& assets::detail::generic_basic_store_iterator::operator-=(const difference_type n) +{ + return (*this) += -n; +} + +template +assets::detail::generic_basic_store_iterator assets::detail::generic_basic_store_iterator::operator+(const difference_type n) const +{ + auto tmp = *this; + return tmp += n; // TODO clion says n is unused +} + +template +assets::detail::generic_basic_store_iterator assets::detail::generic_basic_store_iterator::operator-(const difference_type n) const +{ + auto tmp = *this; + return tmp -= n; // TODO clion says n is unused +} + +template +typename assets::detail::generic_basic_store_iterator::difference_type +assets::detail::generic_basic_store_iterator::operator-(const generic_basic_store_iterator& other) const +{ + return static_cast(m_index) - static_cast(other.m_index); +} + +template +typename assets::detail::generic_basic_store_iterator::reference assets::detail::generic_basic_store_iterator::operator[]( + const difference_type n +) const { + return *(*this + n); +} + +template +bool assets::detail::generic_basic_store_iterator::operator==(const generic_basic_store_iterator& other) const +{ + return m_ids == other.m_ids and m_index == other.m_index; +} + +template +bool assets::detail::generic_basic_store_iterator::operator!=(const generic_basic_store_iterator& other) const +{ + return not (*this == other); +} + +template +bool assets::detail::generic_basic_store_iterator::operator<(const generic_basic_store_iterator& other) const +{ + return m_index < other.m_index; +} + +template +bool assets::detail::generic_basic_store_iterator::operator<=(const generic_basic_store_iterator& other) const +{ + return m_index <= other.m_index; +} + +template +bool assets::detail::generic_basic_store_iterator::operator>(const generic_basic_store_iterator& other) const +{ + return m_index > other.m_index; +} + +template +bool assets::detail::generic_basic_store_iterator::operator>=(const generic_basic_store_iterator& other) const +{ + return m_index >= other.m_index; +} + +template +typename assets::detail::generic_basic_store_iterator::reference +assets::detail::generic_basic_store_iterator::dereference() const +{ + return { + m_ids[m_index], + m_data[m_index] + }; +} + + +template +bool assets::detail::generic_basic_store::insert(const ID id, const T& data) +{ + auto lock = std::unique_lock{ m_mutex }; + + const auto result = unsafe_find(id); + + return unsafe_insert(result.first, id, data); +} + + +template +bool assets::detail::generic_basic_store::insert(iterator it, const ID id, const T& data) +{ + auto lock = std::unique_lock{ m_mutex }; + + return unsafe_insert(it, id, data); +} + +template +std::pair::iterator, bool> assets::detail::generic_basic_store::find(ID id) +{ + auto lock = std::shared_lock{ m_mutex }; + + return unsafe_find(id); +} + +template +std::pair::const_iterator, bool> assets::detail::generic_basic_store::find(ID id) const +{ + auto lock = std::shared_lock{ m_mutex }; + + return unsafe_find(id); +} + +template +bool assets::detail::generic_basic_store::unsafe_insert(iterator it, const ID id, const T& data) +{ + const auto index = it.m_index; + + if (index != m_ids.size() and m_ids[index] == id) + { + m_data[index] = data; + return false; + } + + m_ids.insert(m_ids.begin() + index, id); + m_data.insert(m_data.begin() + index, data); + + return true; +} + +template +std::pair::iterator, bool> assets::detail::generic_basic_store::unsafe_find(ID id) +{ + const auto it = std::ranges::lower_bound(m_ids, id); + + const auto found = it != m_ids.end() and *it == id; + const auto index = std::distance(m_ids.begin(), it); + + return { begin() + index, found }; +} + +template +std::pair::const_iterator, bool> assets::detail::generic_basic_store::unsafe_find(ID id) const +{ + const auto it = std::ranges::lower_bound(m_ids, id); + + const auto found = it != m_ids.end() and *it == id; + const auto index = std::distance(m_ids.begin(), it); + + return { begin() + index, found }; +} + +template +void assets::detail::generic_basic_store::remove(iterator it) +{ + auto lock = std::unique_lock{ m_mutex }; + const auto index = it.m_index; + m_data.erase(m_data.begin() + index); m_ids.erase(m_ids.begin() + index); } -template -void generic_basic_store::clear() +template +void assets::detail::generic_basic_store::clear() { + auto lock = std::unique_lock{ m_mutex }; m_data.clear(); m_ids.clear(); } -template -std::span generic_basic_store::data() -{ - return m_data; +template +std::shared_lock assets::detail::generic_basic_store::acquire_read_lock() const { + return std::shared_lock{ m_mutex }; } -template -std::span generic_basic_store::data() const -{ - return m_data; +template +std::unique_lock assets::detail::generic_basic_store::acquire_write_lock() { + return std::unique_lock{ m_mutex }; +} + +template +typename assets::detail::generic_basic_store::iterator assets::detail::generic_basic_store::begin() +{ + return iterator{ + m_ids.data(), + m_data.begin(), + 0 + }; +} + +template +typename assets::detail::generic_basic_store::iterator assets::detail::generic_basic_store::end() +{ + return iterator{ + m_ids.data(), + m_data.begin(), + m_ids.size() + }; +} + +template +typename assets::detail::generic_basic_store::const_iterator assets::detail::generic_basic_store::begin() const +{ + return const_iterator{ + m_ids.data(), + m_data.begin(), + 0 + }; +} + +template +typename assets::detail::generic_basic_store::const_iterator assets::detail::generic_basic_store::end() const +{ + return const_iterator{ + m_ids.data(), + m_data.begin(), + m_ids.size() + }; +} + +template +typename assets::detail::generic_basic_store::const_iterator assets::detail::generic_basic_store::cbegin() const +{ + return this->begin(); +} + +template +typename assets::detail::generic_basic_store::const_iterator assets::detail::generic_basic_store::cend() const +{ + return this->end(); } diff --git a/source/assets/data_stores/generic/generic_material_store.ipp b/source/assets/data_stores/generic/generic_material_store.ipp index 41613c2..2209bcf 100644 --- a/source/assets/data_stores/generic/generic_material_store.ipp +++ b/source/assets/data_stores/generic/generic_material_store.ipp @@ -3,7 +3,7 @@ #endif #include -#include +#include #include #include #include @@ -14,7 +14,7 @@ assets::detail::generic_material_store_iterator::generic_material_store_i id_iterator_type ids, const component_iterator_type& components, flag_count_iterator_type flag_counts, - std::size_t index, + const size_type index, const offsets_type& offsets ) : m_ids{ ids }, @@ -195,7 +195,7 @@ assets::detail::generic_material_store_iterator::dereference(std::index_s } template -std::tuple...> assets::detail::generic_material_store::component_iterators() +std::tuple...> assets::detail::generic_material_store>::component_iterators() { return [&](std::index_sequence) { @@ -205,7 +205,7 @@ std::tuple...> assets::detail::generic_material_store -std::tuple>...> assets::detail::generic_material_store::component_iterators() const +std::tuple>...> assets::detail::generic_material_store>::component_iterators() const { return [&](std::index_sequence) { @@ -215,8 +215,8 @@ std::tuple>...> assets::detail::generic_ } template -std::array::count_type, 1 + sizeof...(Ts)> -assets::detail::generic_material_store::array_counts() const +std::array>::count_type, 1 + sizeof...(Ts)> +assets::detail::generic_material_store>::array_counts() const { return [&](std::index_sequence) { @@ -228,84 +228,139 @@ assets::detail::generic_material_store::array_counts() const } template -typename assets::detail::generic_material_store::id_type assets::detail::generic_material_store::add( - const component_set& material -) { +bool assets::detail::generic_material_store>::insert(const id_type id, const data_type& data) +{ + auto lock = std::unique_lock{ m_mutex }; - const auto id = id_type{ m_next_data_id.index++ }; - m_ids.push_back(id); + const auto result = unsafe_find(id); - auto component_flags = component_flag_type{}; + return unsafe_insert(result.first, id, data); +} + +template +bool assets::detail::generic_material_store>::insert(iterator it, const id_type id, const data_type& data) +{ + auto lock = std::unique_lock{ m_mutex }; + + return unsafe_insert(it, id, data); +} + +template +std::pair>::iterator, bool> assets::detail::generic_material_store>::find(id_type id) +{ + auto lock = std::shared_lock{ m_mutex }; + + return unsafe_find(id); + +} + +template +std::pair>::const_iterator, bool> assets::detail::generic_material_store>::find(id_type id) const +{ + auto lock = std::shared_lock{ m_mutex }; + + return unsafe_find(id); +} + + +template +bool assets::detail::generic_material_store>::unsafe_insert(iterator it, const id_type id, const data_type& data) +{ + const auto index = it.m_index; + const auto new_entry = index == m_ids.size() or m_ids[index] != id; + const auto src_component_flags = data.component_flags; + // TODO Can currently not trust the material components, that should change! + + if (new_entry) + { + m_ids.insert(m_ids.begin() + index, id); + m_component_flag_counts.insert(m_component_flag_counts.begin() + index, src_component_flags); + } + + auto& dst_component_flags = m_component_flag_counts[index]; [&](std::integer_sequence) { - if (const auto& component_opt = std::get(material.data)) + const auto is_component_enabled = src_component_flags & component_flag_type{ 1 } << Is; + const auto was_component_enabled = ( + new_entry + ? static_cast(dst_component_flags & component_flag_type{ 1 } << Is) + : component_flag_type{} + ); + + const auto& src_component = std::get(data.components); + auto& dst_component_array = std::get(m_component_arrays); + const auto component_index = it.m_offsets[Is]; + const auto dst_component_it = dst_component_array.begin() + component_index; + + if (is_component_enabled) { - std::get(material.data).push_back(*component_opt); - component_flags |= component_flag_type{ 1 } << Is; + if (was_component_enabled) + { + *dst_component_it = *src_component; + } + else + { + dst_component_array.insert(dst_component_it, *src_component); + } + } + else if (was_component_enabled) + { + dst_component_array.erase(dst_component_it); } } (std::index_sequence_for{}); - m_component_flag_counts.push_back(component_flags); + dst_component_flags = src_component_flags; - return id; + return new_entry; } template -std::pair::iterator_type, bool> assets::detail::generic_material_store::find(id_type id) +std::pair>::iterator, bool> assets::detail::generic_material_store>::unsafe_find(id_type id) { - const auto id_it = std::ranges::upper_bound(m_ids, id); + const auto it = std::ranges::lower_bound(m_ids, id); - const auto match = ( - id_it != m_ids.begin() and - *std::prev(id_it) == id - ); + const auto found = it != m_ids.end() and *it == id; + const auto index = std::distance(m_ids.begin(), it); - const auto index = id_it - m_ids.begin() - match; + return { begin() + index, found }; - auto it = begin(); - it += index; - - return { it, match }; } template -std::pair::const_iterator, bool> assets::detail::generic_material_store::find(id_type id) const +std::pair>::const_iterator, bool> assets::detail::generic_material_store>::unsafe_find(id_type id) const { - const auto id_it = std::ranges::upper_bound(m_ids, id); + const auto it = std::ranges::lower_bound(m_ids, id); - const auto match = ( - id_it != m_ids.begin() and - *std::prev(id_it) == id - ); + const auto found = it != m_ids.end() and *it == id; + const auto index = std::distance(m_ids.begin(), it); - const auto index = id_it - m_ids.begin() - match; - - auto it = begin(); - it += index; - - return { it, match }; + return { begin() + index, found }; } template -void assets::detail::generic_material_store::remove(const iterator_type& it) +void assets::detail::generic_material_store>::remove(const iterator& it) { + auto lock = std::unique_lock{ m_mutex }; + m_ids.erase(m_ids.begin() + it.m_index); return [&](std::index_sequence) { - auto& component_vector = std::get(m_component_arrays); - (component_vector.erase(component_vector.begin() + it.m_offsets[Is]), ...); + auto& component_array = std::get(m_component_arrays); + (component_array.erase(component_array.begin() + it.m_offsets[Is]), ...); } (std::index_sequence_for{}); m_component_flag_counts.erase(m_component_flag_counts.begin() + it.m_index); } template -void assets::detail::generic_material_store::clear() +void assets::detail::generic_material_store>::clear() { + auto lock = std::unique_lock{ m_mutex }; + m_ids.clear(); [&](std::index_sequence) { @@ -315,9 +370,19 @@ void assets::detail::generic_material_store::clear() } template -typename assets::detail::generic_material_store::iterator_type assets::detail::generic_material_store::begin() +std::shared_lock assets::detail::generic_material_store>::acquire_read_lock() const { + return std::shared_lock{ m_mutex }; +} + +template +std::unique_lock assets::detail::generic_material_store>::acquire_write_lock() { + return std::unique_lock{ m_mutex }; +} + +template +typename assets::detail::generic_material_store>::iterator assets::detail::generic_material_store>::begin() { - return iterator_type{ + return iterator{ m_ids.data(), component_iterators(), m_component_flag_counts.data(), @@ -327,9 +392,9 @@ typename assets::detail::generic_material_store::iterator_type assets::de } template -typename assets::detail::generic_material_store::iterator_type assets::detail::generic_material_store::end() +typename assets::detail::generic_material_store>::iterator assets::detail::generic_material_store>::end() { - return iterator_type{ + return iterator{ m_ids.data(), component_iterators(), m_component_flag_counts.data(), @@ -339,7 +404,7 @@ typename assets::detail::generic_material_store::iterator_type assets::de } template -typename assets::detail::generic_material_store::const_iterator assets::detail::generic_material_store::begin() const +typename assets::detail::generic_material_store>::const_iterator assets::detail::generic_material_store>::begin() const { return const_iterator{ m_ids.data(), @@ -351,7 +416,7 @@ typename assets::detail::generic_material_store::const_iterator assets::d } template -typename assets::detail::generic_material_store::const_iterator assets::detail::generic_material_store::end() const +typename assets::detail::generic_material_store>::const_iterator assets::detail::generic_material_store>::end() const { return const_iterator{ m_ids.data(), @@ -363,24 +428,13 @@ typename assets::detail::generic_material_store::const_iterator assets::d } template -typename assets::detail::generic_material_store::const_iterator assets::detail::generic_material_store::cbegin() const +typename assets::detail::generic_material_store>::const_iterator assets::detail::generic_material_store>::cbegin() const { - return const_cast(this)->begin(); + return this->begin(); } template -typename assets::detail::generic_material_store::const_iterator assets::detail::generic_material_store::cend() const +typename assets::detail::generic_material_store>::const_iterator assets::detail::generic_material_store>::cend() const { - return const_cast(this)->end(); -} - -template -typename assets::detail::generic_material_store::view_type assets::detail::generic_material_store::view() -{ - return { begin(), end() }; -} -template -typename assets::detail::generic_material_store::const_view_type assets::detail::generic_material_store::view() const -{ - return { begin(), end() }; + return this->end(); } diff --git a/source/assets/data_stores/generic/generic_mesh_store.ipp b/source/assets/data_stores/generic/generic_mesh_store.ipp index 8aea46b..7a0e8d5 100644 --- a/source/assets/data_stores/generic/generic_mesh_store.ipp +++ b/source/assets/data_stores/generic/generic_mesh_store.ipp @@ -8,6 +8,8 @@ #include #include #include +#include +#include "util/vector_replace_range.hpp" template assets::detail::generic_mesh_store_iterator::generic_mesh_store_iterator( @@ -16,7 +18,7 @@ assets::detail::generic_mesh_store_iterator::generic_mesh_store_iterator( const component_iterator_type& components, material_id_iterator_type material_ids, flag_count_iterator_type flag_counts, - std::size_t index, + const size_type index, const offsets_type& offsets ) : m_ids{ ids }, @@ -162,14 +164,14 @@ void assets::detail::generic_mesh_store_iterator::calc_offsets( while (n--) { - const auto& [ flags, index_count, component_count ] = m_flag_counts[m_index]; + const auto& [ flags, triangle_count, component_count ] = m_flag_counts[m_index]; - std::get<0>(m_offsets) += step * index_count; + std::get<0>(m_offsets) += step * difference_type{ triangle_count }; ([&] { if (is_component_enabled(flags)) { - std::get<1 + Is>(m_offsets) += step * component_count; + std::get<1 + Is>(m_offsets) += step * difference_type{ component_count }; } }(), ...); @@ -182,15 +184,15 @@ template typename assets::detail::generic_mesh_store_iterator::reference assets::detail::generic_mesh_store_iterator::dereference(std::index_sequence) const { - const auto& [ flags, index_count, component_count ] = m_flag_counts[m_index]; + const auto& [ flags, triangle_count, component_count ] = m_flag_counts[m_index]; return std::make_pair( m_ids[m_index], mesh_view{ .component_flags = flags, - .indices = std::span( - m_indices[m_offsets[0]], - index_count + .triangles = std::span( + &m_triangles[m_offsets[0]], + triangle_count ), .vertex_component_arrays = std::make_tuple( std::span( @@ -205,7 +207,7 @@ assets::detail::generic_mesh_store_iterator::dereference(std::index_seque } template -std::tuple...> assets::detail::generic_mesh_store::component_iterators() +std::tuple...> assets::detail::generic_mesh_store>::component_iterators() { return [&](std::index_sequence) { @@ -215,7 +217,7 @@ std::tuple...> assets::detail::generic_mesh_store: } template -std::tuple>...> assets::detail::generic_mesh_store::component_iterators() const +std::tuple>...> assets::detail::generic_mesh_store>::component_iterators() const { return [&](std::index_sequence) { @@ -225,13 +227,13 @@ std::tuple>...> assets::detail::generic_ } template -std::array::count_type, 1 + sizeof...(Ts)> -assets::detail::generic_mesh_store::array_counts() const +std::array>::count_type, 1 + sizeof...(Ts)> +assets::detail::generic_mesh_store>::array_counts() const { return [&](std::index_sequence) { return std::array{ - m_indices.size(), + m_triangles.size(), std::get(m_component_arrays).size()... }; } @@ -239,129 +241,191 @@ assets::detail::generic_mesh_store::array_counts() const } template -typename assets::detail::generic_mesh_store::id_type assets::detail::generic_mesh_store::add( - const mesh_data& mesh -) { +bool assets::detail::generic_mesh_store>::insert(const id_type id, const data_type& data) +{ + auto lock = std::unique_lock{ m_mutex }; - const auto id = id_type{ m_next_data_id.index++ }; - m_ids.push_back(id); + const auto result = unsafe_find(id); - const auto& vertices = mesh.vertices; - const auto& triangles = mesh.triangles(); - const auto indices = std::span(triangles.front().data(), triangles.size() * 3); + return unsafe_insert(result.first, id, data); +} - auto component_flags = component_flag_type{}; - auto min_component_count = count_type{}; +template +bool assets::detail::generic_mesh_store>::insert(iterator it, const id_type id, const data_type& data) +{ + auto lock = std::unique_lock{ m_mutex }; + + return unsafe_insert(it, id, data); +} + +template +std::pair>::iterator, bool> assets::detail::generic_mesh_store>::find(id_type id) +{ + auto lock = std::shared_lock{ m_mutex }; + + return unsafe_find(id); +} + +template +std::pair>::const_iterator, bool> assets::detail::generic_mesh_store>::find(id_type id) const +{ + auto lock = std::shared_lock{ m_mutex }; + + return unsafe_find(id); +} + + +template +bool assets::detail::generic_mesh_store>::unsafe_insert(iterator it, const id_type id, const data_type& data) +{ + const auto index = it.m_index; + const auto new_entry = index == m_ids.size() or m_ids[index] != id; + const auto src_component_flags = data.component_flags; + // TODO Can currently not trust the material components, that should change! + + auto vertex_count = ( + data.component_flags == component_flag_type{} + ? count_type{} + : std::numeric_limits::max() + ); - // finding out correct component flags and count [&](std::integer_sequence) { - const auto& component_array = std::get(vertices); + const auto& component_array = std::get(data.component_arrays); if (not component_array.empty()) { + // TODO check count const auto component_count = static_cast(component_array.size()); - if (min_component_count != 0 and component_count < min_component_count) + if (component_count != 0 and component_count < vertex_count) { - min_component_count = component_count; + vertex_count = component_count; } - component_flags |= component_flag_type{ 1 } << Is; } } (std::index_sequence_for{}); - // Insert indices - m_indices.insert(m_indices.end(), indices.begin(), indices.end()); + auto dst_component_flags = component_flag_type{}; + auto dst_index_count = count_type{}; + auto dst_vertex_count = count_type{}; + + const auto src_component_flag_count = std::tuple{ + src_component_flags, + data.triangles().size(), + vertex_count + }; + + if (new_entry) { + m_ids.insert(m_ids.begin() + index, id); + m_component_flag_counts.insert( + m_component_flag_counts.begin() + index, + src_component_flag_count + ); + m_material_ids.insert(m_material_ids.begin() + index, data.material()); + } + else + { + std::tie(dst_component_flags, dst_index_count, dst_vertex_count) = m_component_flag_counts[index]; + m_component_flag_counts[index] = src_component_flag_count; + m_material_ids[index] = data.material(); + } + + // TODO check + const auto dst_triangle_it = m_triangles.begin() + it.m_offsets.front(); + ztu::replace_range( + m_triangles, + dst_triangle_it, + dst_triangle_it + dst_index_count, + data.triangles().begin(), + data.triangles().end() + ); - // Insert vertex components [&](std::integer_sequence) { - const auto& src_array = std::get(vertices); - auto& dst_array = std::get(m_component_arrays); + const auto is_component_enabled = src_component_flags & component_flag_type{ 1 } << Is; + const auto was_component_enabled = ( + new_entry + ? static_cast(dst_component_flags & component_flag_type{ 1 } << Is) + : component_flag_type{} + ); - if (not src_array.empty()) - { - dst_array.insert(dst_array.end(), src_array.begin(), src_array.begin() + min_component_count); - } + const auto& src_component_array = std::get(data.component_arrays); + auto& dst_component_array = std::get(m_component_arrays); + const auto component_index = it.m_offsets[1 + Is]; + const auto dst_component_it = dst_component_array.begin() + component_index; + + ztu::replace_range( + dst_component_array, + dst_component_it, + dst_component_it + dst_vertex_count, + src_component_array.begin(), + src_component_array.begin() + vertex_count + ); } (std::index_sequence_for{}); - // Insert material - m_material_ids.emplace_back(mesh.material_id()); - - // TODO check count - m_component_flag_counts.emplace_back( - mesh.component_flags, - static_cast(indices.size()), - min_component_count - ); - - return id; + return new_entry; } template -std::pair::iterator_type, bool> assets::detail::generic_mesh_store::find(id_type id) +std::pair>::iterator, bool> assets::detail::generic_mesh_store>::unsafe_find(id_type id) { - const auto id_it = std::ranges::upper_bound(m_ids, id); + const auto it = std::ranges::lower_bound(m_ids, id); - const auto match = ( - id_it != m_ids.begin() and - *std::prev(id_it) == id - ); + const auto found = it != m_ids.end() and *it == id; + const auto index = std::distance(m_ids.begin(), it); - const auto index = id_it - m_ids.begin() - match; - - auto it = begin(); - it += index; - - return { it, match }; + return { begin() + index, found }; } template -std::pair::const_iterator, bool> assets::detail::generic_mesh_store::find(id_type id) const +std::pair>::const_iterator, bool> assets::detail::generic_mesh_store>::unsafe_find(id_type id) const { - const auto id_it = std::ranges::upper_bound(m_ids, id); + const auto it = std::ranges::lower_bound(m_ids, id); - const auto match = ( - id_it != m_ids.begin() and - *std::prev(id_it) == id - ); + const auto found = it != m_ids.end() and *it == id; + const auto index = std::distance(m_ids.begin(), it); - const auto index = id_it - m_ids.begin() - match; - - auto it = begin(); - it += index; - - return { it, match }; + return { begin() + index, found }; } template -void assets::detail::generic_mesh_store::remove(const iterator_type& it) +void assets::detail::generic_mesh_store>::remove(const iterator& it) { - m_ids.erase(m_ids.begin() + it.m_index); + auto lock = std::unique_lock{ m_mutex }; - m_indices.erase(m_indices.begin() + it.m_offsets[0]); + const auto index = it.m_index; + + const auto [ component_flags, triangle_count, vertex_count ] = m_component_flag_counts[index]; + + m_ids.erase(m_ids.begin() + index); + + m_triangles.erase(m_triangles.begin() + it.m_offsets[0], triangle_count); + + m_component_flag_counts.erase(m_component_flag_counts.begin() + index); [&](std::index_sequence) { ([&]{ - auto& component_vector = std::get(m_component_arrays); - const auto begin = component_vector.begin() + it.m_offsets[1 + Is]; - const auto end = begin + it.m_flag_counts[it.m_index]; - component_vector.erase(begin, end); + if ( component_flags & component_flag_type{ 1 } << Is) + { + auto& component_array = std::get(m_component_arrays); + const auto component_it = component_array.begin() + it.m_offsets[1 + Is]; + component_array.erase(component_it, component_it + vertex_count); + } }(), ...); } (std::index_sequence_for{}); - m_material_ids.erase(m_material_ids.begin() + it.m_index); - - m_component_flag_counts.erase(m_component_flag_counts.begin() + it.m_index); + m_material_ids.erase(m_material_ids.begin() + index); } template -void assets::detail::generic_mesh_store::clear() +void assets::detail::generic_mesh_store>::clear() { + auto lock = std::unique_lock{ m_mutex }; + m_ids.clear(); - m_indices.clear(); + m_triangles.clear(); [&](std::index_sequence) { std::get(m_component_arrays).clear(); @@ -371,11 +435,21 @@ void assets::detail::generic_mesh_store::clear() } template -typename assets::detail::generic_mesh_store::iterator_type assets::detail::generic_mesh_store::begin() +std::shared_lock assets::detail::generic_mesh_store>::acquire_read_lock() const { + return std::shared_lock{ m_mutex }; +} + +template +std::unique_lock assets::detail::generic_mesh_store>::acquire_write_lock() { + return std::unique_lock{ m_mutex }; +} + +template +typename assets::detail::generic_mesh_store>::iterator assets::detail::generic_mesh_store>::begin() { - return iterator_type{ + return iterator{ m_ids.data(), - m_indices.data(), + m_triangles.data(), component_iterators(), m_material_ids.data(), m_component_flag_counts.data(), @@ -385,25 +459,25 @@ typename assets::detail::generic_mesh_store::iterator_type assets::detail } template -typename assets::detail::generic_mesh_store::iterator_type assets::detail::generic_mesh_store::end() +typename assets::detail::generic_mesh_store>::iterator assets::detail::generic_mesh_store>::end() { - return iterator_type{ + return iterator{ m_ids.data(), - m_indices.data(), + m_triangles.data(), component_iterators(), m_material_ids.data(), m_component_flag_counts.data(), - m_component_flag_counts.size(), + m_ids.size(), array_counts() }; } template -typename assets::detail::generic_mesh_store::const_iterator assets::detail::generic_mesh_store::begin() const +typename assets::detail::generic_mesh_store>::const_iterator assets::detail::generic_mesh_store>::begin() const { return const_iterator{ m_ids.data(), - m_indices.data(), + m_triangles.data(), component_iterators(), m_material_ids.data(), m_component_flag_counts.data(), @@ -413,11 +487,11 @@ typename assets::detail::generic_mesh_store::const_iterator assets::detai } template -typename assets::detail::generic_mesh_store::const_iterator assets::detail::generic_mesh_store::end() const +typename assets::detail::generic_mesh_store>::const_iterator assets::detail::generic_mesh_store>::end() const { return const_iterator{ m_ids.data(), - m_indices.data(), + m_triangles.data(), component_iterators(), m_material_ids.data(), m_component_flag_counts.data(), @@ -427,24 +501,13 @@ typename assets::detail::generic_mesh_store::const_iterator assets::detai } template -typename assets::detail::generic_mesh_store::const_iterator assets::detail::generic_mesh_store::cbegin() const +typename assets::detail::generic_mesh_store>::const_iterator assets::detail::generic_mesh_store>::cbegin() const { return const_cast(this)->begin(); } template -typename assets::detail::generic_mesh_store::const_iterator assets::detail::generic_mesh_store::cend() const +typename assets::detail::generic_mesh_store>::const_iterator assets::detail::generic_mesh_store>::cend() const { return const_cast(this)->end(); } - -template -typename assets::detail::generic_mesh_store::view_type assets::detail::generic_mesh_store::view() -{ - return { begin(), end() }; -} -template -typename assets::detail::generic_mesh_store::const_view_type assets::detail::generic_mesh_store::view() const -{ - return { begin(), end() }; -} diff --git a/source/assets/data_stores/generic/generic_point_cloud_store.ipp b/source/assets/data_stores/generic/generic_point_cloud_store.ipp index 0067782..2bea055 100644 --- a/source/assets/data_stores/generic/generic_point_cloud_store.ipp +++ b/source/assets/data_stores/generic/generic_point_cloud_store.ipp @@ -13,8 +13,8 @@ template assets::detail::generic_point_cloud_store_iterator::generic_point_cloud_store_iterator( id_iterator_type ids, const component_iterator_type& components, - const flag_count_iterator_type flag_counts, - std::size_t index, + flag_count_iterator_type flag_counts, + const size_type index, const offsets_type& offsets ) : m_ids{ ids }, @@ -196,7 +196,7 @@ assets::detail::generic_point_cloud_store_iterator::dereference(std::inde } template -std::tuple...> assets::detail::generic_point_cloud_store::component_iterators() +std::tuple...> assets::detail::generic_point_cloud_store>::component_iterators() { return [&](std::index_sequence) { @@ -206,7 +206,7 @@ std::tuple...> assets::detail::generic_point_cloud_store< } template -std::tuple>...> assets::detail::generic_point_cloud_store::component_iterators() const +std::tuple>...> assets::detail::generic_point_cloud_store>::component_iterators() const { return [&](std::index_sequence) { @@ -216,8 +216,8 @@ std::tuple>...> assets::detail::generic_ } template -std::array::count_type, 1 + sizeof...(Ts)> -assets::detail::generic_point_cloud_store::array_counts() const +std::array>::count_type, 1 + sizeof...(Ts)> +assets::detail::generic_point_cloud_store>::array_counts() const { return [&](std::index_sequence) { @@ -229,113 +229,163 @@ assets::detail::generic_point_cloud_store::array_counts() const } template -typename assets::detail::generic_point_cloud_store::id_type assets::detail::generic_point_cloud_store::add( - const id_type id, - const data_type& point_cloud -) { +bool assets::detail::generic_point_cloud_store>::insert(const id_type id, const data_type& data) +{ + auto lock = std::unique_lock{ m_mutex }; - m_ids.push_back(id); + const auto result = unsafe_find(id); - const auto& vertices = point_cloud.component_arrays; + return unsafe_insert(result.first, id, data); +} - auto component_flags = component_flag_type{}; - auto min_component_count = count_type{}; +template +std::pair>::iterator, bool> assets::detail::generic_point_cloud_store>::find(id_type id) +{ + auto lock = std::shared_lock{ m_mutex }; + + return unsafe_find(id); +} + +template +std::pair>::const_iterator, bool> assets::detail::generic_point_cloud_store>::find(id_type id) const +{ + auto lock = std::shared_lock{ m_mutex }; + + return unsafe_find(id); +} + +template +bool assets::detail::generic_point_cloud_store>::unsafe_insert(iterator it, const id_type id, const data_type& data) +{ + const auto index = it.m_index; + const auto new_entry = index == m_ids.size() or m_ids[index] != id; + const auto src_component_flags = data.component_flags; + // TODO Can currently not trust the material components, that should change! + + auto vertex_count = ( + data.component_flags == component_flag_type{} + ? count_type{} + : std::numeric_limits::max() + ); - // finding out correct component flags and count [&](std::integer_sequence) { - const auto& component_array = std::get(vertices); + const auto& component_array = std::get(data.component_arrays); if (not component_array.empty()) { + // TODO check count const auto component_count = static_cast(component_array.size()); - if (min_component_count != 0 and component_count < min_component_count) + if (component_count != 0 and component_count < vertex_count) { - min_component_count = component_count; + vertex_count = component_count; } - component_flags |= component_flag_type{ 1 } << Is; } } (std::index_sequence_for{}); - // Insert vertex components + auto dst_component_flags = component_flag_type{}; + auto dst_index_count = count_type{}; + auto dst_vertex_count = count_type{}; + + const auto src_component_flag_count = std::tuple{ + src_component_flags, + vertex_count + }; + + if (new_entry) { + m_ids.insert(m_ids.begin() + index, id); + m_component_flag_counts.insert( + m_component_flag_counts.begin() + index, + src_component_flag_count + ); + } + else + { + std::tie(dst_component_flags, dst_index_count, dst_vertex_count) = m_component_flag_counts[index]; + m_component_flag_counts[index] = src_component_flag_count; + } + [&](std::integer_sequence) { - const auto& src_array = std::get(vertices); - auto& dst_array = std::get(m_component_arrays); + const auto is_component_enabled = src_component_flags & component_flag_type{ 1 } << Is; + const auto was_component_enabled = ( + new_entry + ? static_cast(dst_component_flags & component_flag_type{ 1 } << Is) + : component_flag_type{} + ); - if (not src_array.empty()) - { - dst_array.insert(dst_array.end(), src_array.begin(), src_array.begin() + min_component_count); - } + const auto& src_component_array = std::get(data.component_arrays); + auto& dst_component_array = std::get(m_component_arrays); + const auto component_index = it.m_offsets[1 + Is]; + const auto dst_component_it = dst_component_array.begin() + component_index; + + ztu::replace_range( + dst_component_array, + dst_component_it, + dst_component_it + dst_vertex_count, + src_component_array.begin(), + src_component_array.begin() + vertex_count + ); } (std::index_sequence_for{}); - // TODO check count - m_component_flag_counts.emplace_back( - point_cloud.component_flags, - min_component_count - ); - - return id; + return new_entry; } template -std::pair::iterator_type, bool> assets::detail::generic_point_cloud_store::find(id_type id) +std::pair>::iterator, bool> assets::detail::generic_point_cloud_store>::unsafe_find(id_type id) { - const auto id_it = std::ranges::upper_bound(m_ids, id); + const auto it = std::ranges::lower_bound(m_ids, id); - const auto match = ( - id_it != m_ids.begin() and - *std::prev(id_it) == id - ); + const auto found = it != m_ids.end() and *it == id; + const auto index = std::distance(m_ids.begin(), it); - const auto index = id_it - m_ids.begin() - match; - - auto it = begin(); - it += index; - - return { it, match }; + return { begin() + index, found }; } template -std::pair::const_iterator, bool> assets::detail::generic_point_cloud_store::find(id_type id) const +std::pair>::const_iterator, bool> assets::detail::generic_point_cloud_store>::unsafe_find(id_type id) const { - const auto id_it = std::ranges::upper_bound(m_ids, id); + const auto it = std::ranges::lower_bound(m_ids, id); - const auto match = ( - id_it != m_ids.begin() and - *std::prev(id_it) == id - ); + const auto found = it != m_ids.end() and *it == id; + const auto index = std::distance(m_ids.begin(), it); - const auto index = id_it - m_ids.begin() - match; - - auto it = begin(); - it += index; - - return { it, match }; + return { begin() + index, found }; } template -void assets::detail::generic_point_cloud_store::remove(const iterator_type& it) +void assets::detail::generic_point_cloud_store>::remove(const iterator& it) { + auto lock = std::unique_lock{ m_mutex }; + + const auto index = it.m_index; + + const auto [ component_flags, triangle_count, vertex_count ] = m_component_flag_counts[index]; + + m_ids.erase(m_ids.begin() + index); + + m_component_flag_counts.erase(m_component_flag_counts.begin() + index); + [&](std::index_sequence) { ([&]{ - auto& component_vector = std::get(m_component_arrays); - const auto begin = component_vector.begin() + it.m_offsets[1 + Is]; - const auto end = begin + it.m_flag_counts[it.m_index]; - component_vector.erase(begin, end); + if ( component_flags & component_flag_type{ 1 } << Is) + { + auto& component_array = std::get(m_component_arrays); + const auto component_it = component_array.begin() + it.m_offsets[1 + Is]; + component_array.erase(component_it, component_it + vertex_count); + } }(), ...); } (std::index_sequence_for{}); - - m_component_flag_counts.erase(m_component_flag_counts.begin() + it.m_index); - m_ids.erase(m_ids.begin() + it.m_index); } template -void assets::detail::generic_point_cloud_store::clear() +void assets::detail::generic_point_cloud_store>::clear() { + auto lock = std::unique_lock{ m_mutex }; + m_ids.clear(); [&](std::index_sequence) { @@ -345,9 +395,19 @@ void assets::detail::generic_point_cloud_store::clear() } template -typename assets::detail::generic_point_cloud_store::iterator_type assets::detail::generic_point_cloud_store::begin() +std::shared_lock assets::detail::generic_point_cloud_store>::acquire_read_lock() const { + return std::shared_lock{ m_mutex }; +} + +template +std::unique_lock assets::detail::generic_point_cloud_store>::acquire_write_lock() { + return std::unique_lock{ m_mutex }; +} + +template +typename assets::detail::generic_point_cloud_store>::iterator assets::detail::generic_point_cloud_store>::begin() { - return iterator_type{ + return iterator{ m_ids.data(), component_iterators(), m_component_flag_counts.data(), @@ -357,9 +417,9 @@ typename assets::detail::generic_point_cloud_store::iterator_type assets: } template -typename assets::detail::generic_point_cloud_store::iterator_type assets::detail::generic_point_cloud_store::end() +typename assets::detail::generic_point_cloud_store>::iterator assets::detail::generic_point_cloud_store>::end() { - return iterator_type{ + return iterator{ m_ids.data(), component_iterators(), m_component_flag_counts.data(), @@ -369,7 +429,7 @@ typename assets::detail::generic_point_cloud_store::iterator_type assets: } template -typename assets::detail::generic_point_cloud_store::const_iterator assets::detail::generic_point_cloud_store::begin() const +typename assets::detail::generic_point_cloud_store>::const_iterator assets::detail::generic_point_cloud_store>::begin() const { return const_iterator{ m_ids.data(), @@ -381,7 +441,7 @@ typename assets::detail::generic_point_cloud_store::const_iterator assets } template -typename assets::detail::generic_point_cloud_store::const_iterator assets::detail::generic_point_cloud_store::end() const +typename assets::detail::generic_point_cloud_store>::const_iterator assets::detail::generic_point_cloud_store>::end() const { return const_iterator{ m_ids.data(), @@ -393,13 +453,13 @@ typename assets::detail::generic_point_cloud_store::const_iterator assets } template -typename assets::detail::generic_point_cloud_store::const_iterator assets::detail::generic_point_cloud_store::cbegin() const +typename assets::detail::generic_point_cloud_store>::const_iterator assets::detail::generic_point_cloud_store>::cbegin() const { return const_cast(this)->begin(); } template -typename assets::detail::generic_point_cloud_store::const_iterator assets::detail::generic_point_cloud_store::cend() const +typename assets::detail::generic_point_cloud_store>::const_iterator assets::detail::generic_point_cloud_store>::cend() const { return const_cast(this)->end(); } diff --git a/source/assets/data_stores/pose_list_store.ipp b/source/assets/data_stores/pose_list_store.ipp index 77b2174..5c80edd 100644 --- a/source/assets/data_stores/pose_list_store.ipp +++ b/source/assets/data_stores/pose_list_store.ipp @@ -15,7 +15,7 @@ assets::pose_list_store_iterator::pose_list_store_iterator( id_iterator_type ids, pose_iterator_type poses, length_iterator_type lengths, - std::size_t index, + const size_type index, const offset_type& offset ) : m_ids{ ids }, @@ -169,62 +169,94 @@ assets::pose_list_store_iterator::dereference() const ); } -assets::pose_list_store::id_type assets::pose_list_store::add( - const pose_list_id id, - const pose_list_data& pose_list -) { +inline bool assets::pose_list_store::insert(const id_type id, const data_type& data) +{ + auto lock = std::unique_lock{ m_mutex }; - m_ids.push_back(id); + const auto result = find(id); - m_poses.insert(m_poses.end(), pose_list.begin(), pose_list.end()); - - m_lengths.push_back(pose_list.size()); - return id; + return insert(result.first, id, data); } -std::pair assets::pose_list_store::find(id_type id) +inline std::pair assets::pose_list_store::find(id_type id) { - const auto id_it = std::ranges::upper_bound(m_ids, id); + auto lock = std::shared_lock{ m_mutex }; - const auto match = ( - id_it != m_ids.begin() and - *std::prev(id_it) == id + return unsafe_find(id); +} + +inline std::pair assets::pose_list_store::find(id_type id) const +{ + auto lock = std::shared_lock{ m_mutex }; + + return unsafe_find(id); +} + +inline bool assets::pose_list_store::unsafe_insert(iterator it, const id_type id, const data_type& data) +{ + const auto index = it.m_index; + const auto new_entry = index == m_ids.size() or m_ids[index] != id; + // TODO Can currently not trust the material components, that should change! + + + auto dst_pose_count = count_type{}; + + const auto src_pose_count = data.size(); + + if (new_entry) { + m_ids.insert(m_ids.begin() + index, id); + m_lengths.insert(m_lengths.begin() + index, src_pose_count); + } + else + { + dst_pose_count = m_lengths[index]; + m_lengths[index] = src_pose_count; + } + + const auto dst_pose_it = m_poses.begin() + it.m_offset; + + ztu::replace_range( + m_poses, + dst_pose_it, + dst_pose_it + dst_pose_count, + data.begin(), + data.begin() + src_pose_count ); - const auto index = id_it - m_ids.begin() - match; - - auto it = begin(); - it += index; - - return { it, match }; + return new_entry; } -std::pair assets::pose_list_store::find(id_type id) const + +inline std::pair assets::pose_list_store::unsafe_find(id_type id) { - const auto id_it = std::ranges::upper_bound(m_ids, id); + const auto it = std::ranges::lower_bound(m_ids, id); - const auto match = ( - id_it != m_ids.begin() and - *std::prev(id_it) == id - ); + const auto found = it != m_ids.end() and *it == id; + const auto index = std::distance(m_ids.begin(), it); - const auto index = id_it - m_ids.begin() - match; - - auto it = begin(); - it += index; - - return { it, match }; + return { begin() + index, found }; } -void assets::pose_list_store::remove(const iterator_type& it) +inline std::pair assets::pose_list_store::unsafe_find(id_type id) const { - m_ids.erase(m_ids.begin() + it.m_index); + const auto it = std::ranges::lower_bound(m_ids, id); - const auto begin = m_poses.begin() + it.m_offset; - const auto end = begin + it.m_lengths[it.m_index]; - m_poses.erase(begin, end); + const auto found = it != m_ids.end() and *it == id; + const auto index = std::distance(m_ids.begin(), it); - m_lengths.erase(m_lengths.begin() + it.m_index); + return { begin() + index, found }; +} + +void assets::pose_list_store::remove(const iterator& it) +{ + const auto index = it.m_index; + + m_ids.erase(m_ids.begin() + index); + + const auto poses_it = m_poses.begin() + it.m_offset; + m_poses.erase(poses_it, poses_it + m_lengths[index]); + + m_lengths.erase(m_lengths.begin() + index); } void assets::pose_list_store::clear() @@ -234,9 +266,17 @@ void assets::pose_list_store::clear() m_lengths.clear(); } -assets::pose_list_store::iterator_type assets::pose_list_store::begin() +std::shared_lock assets::pose_list_store::acquire_read_lock() const { + return std::shared_lock{ m_mutex }; +} + +std::unique_lock assets::pose_list_store::acquire_write_lock() { + return std::unique_lock{ m_mutex }; +} + +assets::pose_list_store::iterator assets::pose_list_store::begin() { - return iterator_type{ + return iterator{ m_ids.data(), m_poses.data(), m_lengths.data(), @@ -245,9 +285,9 @@ assets::pose_list_store::iterator_type assets::pose_list_store::begin() }; } -assets::pose_list_store::iterator_type assets::pose_list_store::end() +assets::pose_list_store::iterator assets::pose_list_store::end() { - return iterator_type{ + return iterator{ m_ids.data(), m_poses.data(), m_lengths.data(), diff --git a/source/assets/data_stores/shader_source_store.ipp b/source/assets/data_stores/shader_source_store.ipp index ae9dea9..fbb1561 100644 --- a/source/assets/data_stores/shader_source_store.ipp +++ b/source/assets/data_stores/shader_source_store.ipp @@ -17,7 +17,7 @@ assets::shader_source_store_iterator::shader_source_store_iterator( string_iterator_type strings, length_iterator_type lengths, metadata_iterator_type metadata, - std::size_t index, + const size_type index, const offset_type& offset ) : m_ids{ ids }, @@ -172,65 +172,90 @@ assets::shader_source_store_iterator::dereference() const ); } -assets::shader_source_store::id_type assets::shader_source_store::add( - const shader_source_id id, - const shader_source_data& shader_source -) { +bool assets::shader_source_store::insert(const id_type id, const data_type& data) +{ + auto lock = std::unique_lock{ m_mutex }; - m_ids.push_back(id); + const auto result = find(id); - m_strings.reserve(m_strings.size() + shader_source.source.size() + 1); - m_strings.insert(m_strings.end(), shader_source.source.begin(), shader_source.source.end()); - m_strings.push_back('\0'); - - m_lengths.push_back(shader_source.source.size()); - - m_metadata.push_back(shader_source.meta); - - return id; + return insert(result.first, id, data); } -std::pair assets::shader_source_store::find(id_type id) -{ - const auto id_it = std::ranges::upper_bound(m_ids, id); - const auto match = ( - id_it != m_ids.begin() and - *std::prev(id_it) == id + +template +bool assets::shader_source_store::insert(iterator it, const id_type id, const data_type& data) +{ + auto lock = std::unique_lock{ m_mutex }; + + const auto index = it.m_index; + const auto new_entry = index == m_ids.size() or m_ids[index] != id; + + auto dst_source_length = count_type{}; + const auto src_source_length = data.source.size(); + + if (new_entry) { + m_ids.insert(m_ids.begin() + index, id); + m_lengths.insert(m_lengths.begin() + index, src_source_length); + m_metadata.insert(m_metadata.begin() + index, data.meta); + } + else + { + dst_source_length = m_lengths[index]; + m_lengths[index] = src_source_length; + m_metadata[index] = data.meta; + } + + const auto dst_string_it = m_strings.begin() + it.m_offset; + ztu::replace_range( + m_strings, + dst_string_it, + dst_string_it + dst_source_length, + data.source.begin(), + data.source.end() ); - const auto index = id_it - m_ids.begin() - match; + if (new_entry) + { + m_strings.insert(m_strings.begin() + it.m_offset + src_source_length, '\0'); + } - auto it = begin(); - it += index; - - return { it, match }; + return new_entry; } -std::pair assets::shader_source_store::find(id_type id) const +inline std::pair assets::shader_source_store::find(id_type id) { - const auto id_it = std::ranges::upper_bound(m_ids, id); + auto lock = std::shared_lock{ m_mutex }; - const auto match = ( - id_it != m_ids.begin() and - *std::prev(id_it) == id - ); + const auto it = std::ranges::lower_bound(m_ids, id); - const auto index = id_it - m_ids.begin() - match; + const auto found = it != m_ids.end() and *it == id; + const auto index = std::distance(m_ids.begin(), it); - auto it = begin(); - it += index; - - return { it, match }; + return { begin() + index, found }; } -void assets::shader_source_store::remove(const iterator_type& it) +inline std::pair assets::shader_source_store::find(id_type id) const { + auto lock = std::shared_lock{ m_mutex }; + + const auto it = std::ranges::lower_bound(m_ids, id); + + const auto found = it != m_ids.end() and *it == id; + const auto index = std::distance(m_ids.begin(), it); + + return { begin() + index, found }; +} + +void assets::shader_source_store::remove(const iterator& it) +{ + auto lock = std::unique_lock{ m_mutex }; + m_ids.erase(m_ids.begin() + it.m_index); - const auto begin = m_strings.begin() + it.m_offset; - const auto end = begin + it.m_lengths[it.m_index]; - m_strings.erase(begin, end); + const auto strings_begin = m_strings.begin() + it.m_offset; + const auto strings_end = begin + it.m_lengths[it.m_index] + sizeof('\0'); + m_strings.erase(strings_begin, strings_end); m_lengths.erase(m_lengths.begin() + it.m_index); m_metadata.erase(m_metadata.begin() + it.m_index); @@ -238,15 +263,25 @@ void assets::shader_source_store::remove(const iterator_type& it) void assets::shader_source_store::clear() { + auto lock = std::unique_lock{ m_mutex }; + m_ids.clear(); m_strings.clear(); m_lengths.clear(); m_metadata.clear(); } -assets::shader_source_store::iterator_type assets::shader_source_store::begin() +std::shared_lock assets::shader_source_store::acquire_read_lock() const { + return std::shared_lock{ m_mutex }; +} + +std::unique_lock assets::shader_source_store::acquire_write_lock() { + return std::unique_lock{ m_mutex }; +} + +assets::shader_source_store::iterator assets::shader_source_store::begin() { - return iterator_type{ + return iterator{ m_ids.data(), m_strings.data(), m_lengths.data(), @@ -256,9 +291,9 @@ assets::shader_source_store::iterator_type assets::shader_source_store::begin() }; } -assets::shader_source_store::iterator_type assets::shader_source_store::end() +assets::shader_source_store::iterator assets::shader_source_store::end() { - return iterator_type{ + return iterator{ m_ids.data(), m_strings.data(), m_lengths.data(), diff --git a/source/assets/file_parsers/glsl_parser.cpp b/source/assets/file_parsers/glsl_parser.cpp index 5f09b7a..33056ef 100644 --- a/source/assets/file_parsers/glsl_parser.cpp +++ b/source/assets/file_parsers/glsl_parser.cpp @@ -72,6 +72,35 @@ namespace assets::language }; } + +std::error_code assets::glsl_parser::prefetch( + path_id_lookups& +) { + // Nothing to prefetch + return {}; +} + +std::error_code assets::glsl_parser::load( + const path_id_lookups& lookups, + shader_source_store& store, + bool +) { + m_path_buffer.clear(); + lookups.shader_sources.by_extension(".glsl", m_path_buffer); + + auto store_mutex = std::mutex{}; + + std::for_each( + std::execution::parallel_unsequenced_policy{}, + m_path_buffer.begin(), + m_path_buffer.end(), + parser_context{ store, store_mutex } + ); + + return {}; +} + + assets::glsl_parser::parser_context::parser_context( store_type& m_store, std::mutex& m_store_mutex @@ -115,7 +144,7 @@ void assets::glsl_parser::parser_context::operator()(lookup_type::const_pointer { auto lock = std::lock_guard{ *m_store_mutex }; - m_store->add(id, m_buffer); + m_store->insert(id, m_buffer); } } @@ -322,35 +351,6 @@ std::error_code assets::glsl_parser::read_file( return {}; } -std::error_code assets::glsl_parser::prefetch( - path_id_lookups& -) { - // Nothing to prefetch - return {}; -} - -std::error_code assets::glsl_parser::load( - const path_id_lookups& lookups, - shader_source_store& store, - bool -) { - namespace fs = std::filesystem; - - m_path_buffer.clear(); - lookups.shader_sources.by_extension(".glsl", m_path_buffer); - - auto store_mutex = std::mutex{}; - - std::for_each( - std::execution::parallel_unsequenced_policy{}, - m_path_buffer.begin(), - m_path_buffer.end(), - parser_context{ store, store_mutex } - ); - - return {}; -} - bool assets::glsl_parser::parse_geometry_declaration( const std::span values, model_geometry::types& geometry_type diff --git a/source/assets/file_parsers/kitti_parser.cpp b/source/assets/file_parsers/kitti_parser.cpp index 7e61442..6f6463d 100644 --- a/source/assets/file_parsers/kitti_parser.cpp +++ b/source/assets/file_parsers/kitti_parser.cpp @@ -28,7 +28,7 @@ assets::kitti_parser::parser_context::parser_context( m_buffer.normals().reserve(8192); m_buffer.colors().reserve(8192); } - +5 void assets::kitti_parser::parser_context::reset() { m_buffer.clear(); @@ -85,7 +85,7 @@ void assets::kitti_parser::parser_context::operator()(lookup_type::const_pointer { auto lock = std::lock_guard{ *m_store_mutex }; - m_store->add(id, m_buffer); + m_store->insert(id, m_buffer); } } diff --git a/source/assets/file_parsers/mtl_loader.cpp b/source/assets/file_parsers/mtl_parser.cpp similarity index 59% rename from source/assets/file_parsers/mtl_loader.cpp rename to source/assets/file_parsers/mtl_parser.cpp index e4ea0da..82d2f12 100644 --- a/source/assets/file_parsers/mtl_loader.cpp +++ b/source/assets/file_parsers/mtl_parser.cpp @@ -1,4 +1,4 @@ -#include "assets/file_parsers/mtl_loader.hpp" +#include "assets/file_parsers/mtl_parser.hpp" #include #include @@ -7,20 +7,20 @@ #include "util/logger.hpp" #include "util/for_each.hpp" #include "util/line_parser.hpp" +#include -#include "../../../include/assets/data_loaders" - -namespace mtl_loader_error +namespace assets::mtl_parser_error { struct category : std::error_category { [[nodiscard]] const char* name() const noexcept override { - return "mtl_loader"; + return "mtl_parser"; } [[nodiscard]] std::string message(int ev) const override { + // TODO these are incomplete switch (static_cast(ev)) { using enum codes; @@ -47,27 +47,360 @@ struct category : std::error_category } }; -} // namespace mesh_loader_error +} // namespace mtl_parser_error -inline std::error_category& connector_error_category() +inline std::error_category& mtl_parser_error_category() { - static mtl_loader_error::category category; + static assets::mtl_parser_error::category category; return category; } -namespace mtl_loader_error +namespace assets::mtl_parser_error { inline std::error_code make_error_code(codes e) +{ + return { static_cast(e), mtl_parser_error_category() }; +} +} // namespace mtl_loader_error + + +std::error_code assets::mtl_parser::prefetch( + path_id_lookups& lookups +) { + namespace fs = std::filesystem; + using mtl_parser_error::codes; + using mtl_parser_error::make_error_code; + + auto buffer = std::vector(8 * 1024, '\0'); + + auto in = std::ifstream{}; + + auto path_buffer = fs::path{}; + auto filename_buffer = fs::path{}; + + const auto process_file = [&]() + { + in.open(filename_buffer); + if (not in.is_open()) { + ztu::logger::error("Could not open .mtl file '%'", filename_buffer); + return; + } + + filename_buffer.remove_filename(); + + find_textures(buffer, path_buffer, filename_buffer, in, queue.texture.files); + + in.close(); + }; + + // TODO properly extract + for (const auto file : paths.files) + { + filename_buffer.assign(file); + process_file(); + } + + for (const auto directory : paths.directories) + { + for (const auto& file : fs::directory_iterator{ directory }) { + + filename_buffer.assign(file.path()); + + // Avoid heap allocation of .extension() + if (not std::string_view(filename_buffer.c_str()).ends_with(".obj")) + { + continue; + } + + process_file(); + } + } + + return {}; +} + +std::error_code assets::mtl_parser::load( + path_id_lookups& lookups, + data_stores& stores, + bool pedantic +) { + m_path_buffer.clear(); + lookups.material_libraries.by_extension(".mtl", m_path_buffer); + + auto store_mutex = std::mutex{}; + // TODO who protects the material id lookup + // TODO who protects the material store + + std::for_each( + std::execution::parallel_unsequenced_policy{}, + m_path_buffer.begin(), + m_path_buffer.end(), + parser_context{ + lookups.textures, + lookups.materials, + stores.materials, + stores.material_libraries, + store_mutex + } + ); + + return {}; +} + + + +inline std::error_category& connector_error_category() +{ + static assets::mtl_parser_error::category category; + return category; +} + +namespace assets::mtl_parser_error +{ +inline std::error_code make_error_code(const codes e) { return { static_cast(e), connector_error_category() }; } } // namespace mtl_loader_error +assets::mtl_parser::parser_context::parser_context( + const texture_id_lookup& texture_id_lookup, + material_id_lookup& material_id_lookup, + material_store& material_store, + store_type& store, + std::mutex& store_mutex +) : + m_texture_id_lookup{ &texture_id_lookup }, + m_material_id_lookup{ &material_id_lookup }, + m_material_store{ &material_store }, + m_store{ &store }, + m_store_mutex{ &store_mutex } +{ + m_buffer.reserve(32); +} + +void assets::mtl_parser::parser_context::reset() +{ + m_buffer.clear(); +} + +void assets::mtl_parser::parser_context::operator()(lookup_type::const_pointer entry) noexcept +{ + using mtl_parser_error::codes; + using mtl_parser_error::make_error_code; + namespace fs = std::filesystem; + + const auto& [ filename, id ] = *entry; + + // TODO unroll stuff + + auto in = std::ifstream{ filename }; + if (not in.is_open()) + { + ztu::logger::warn("Cannot open mtl file %.", filename); + return; + } + + const auto base_dir = fs::canonical(fs::path(filename).parent_path()); + + auto name = std::string{}; + auto material = material_data{}; + + const auto push_material = [&]() + { + if (not name.empty()) + { + const auto [ id_it, is_new ] = m_material_id_lookup->try_emplace(filename / name); + + const auto material_id = id_it->second; + + m_material_store->emplace(id, material); + + m_buffer.emplace(name, material_id); + } + name = {}; + material = {}; + }; + + const auto ec = ztu::parse_lines( + in, + pedantic, + ztu::make_line_parser("newmtl ", ztu::is_not_repeating, [&](const auto& param) + { + push_material(); + name = param; + + return codes::ok; + }), + ztu::make_line_parser("Ka ", ztu::is_not_repeating, [&](const auto& param) + { + material_components::ambient_filter ambient_filter; + if (parse_numeric_vector(param, ambient_filter) != std::errc{}) [[unlikely]] + { + return codes::malformed_ambient_color; // TODO rename to filter + } + + material.ambient_filter() = ambient_filter; + material.component_flags |= material_components::flags::ambient_filter; + + return codes::ok; + }), + ztu::make_line_parser("Kd ", ztu::is_not_repeating, [&](const auto& param) + { + material_components::diffuse_filter diffuse_filter; + if (parse_numeric_vector(param, diffuse_filter) != std::errc{}) [[unlikely]] + { + return codes::malformed_diffuse_color; + } + + material.diffuse_filter() = diffuse_filter; + material.component_flags |= material_components::flags::diffuse_filter; + + return codes::ok; + }), + ztu::make_line_parser("Ks ", ztu::is_not_repeating, [&](const auto& param) + { + material_components::specular_filter specular_filter; + if (parse_numeric_vector(param, specular_filter) != std::errc{}) [[unlikely]] + { + return codes::malformed_specular_color; + } + + material.specular_filter() = specular_filter; + material.component_flags |= material_components::flags::specular_filter; + + return codes::ok; + }), + ztu::make_line_parser("Ns ", ztu::is_not_repeating, [&](const auto& param) + { + z3d::vec<1, material_components::shininess> shininess; + if (parse_numeric_vector(param, shininess) != std::errc{}) [[unlikely]] + { + return codes::malformed_specular_exponent; + } + + material.shininess() = shininess[0]; + material.component_flags |= material_components::flags::shininess; + + return codes::ok; + }), + ztu::make_line_parser("d ", ztu::is_not_repeating, [&](const auto& param) + { + z3d::vec<1, material_components::alpha> alpha{}; + if (parse_numeric_vector(param, alpha) != std::errc{}) [[unlikely]] + { + return codes::malformed_dissolve; + } + + material.alpha() = alpha[0]; + material.component_flags |= material_components::flags::alpha; + + return codes::ok; + }), + ztu::make_line_parser("map_Ka ", ztu::is_not_repeating, [&](const auto& param) + { + if (const auto texture_id = fetch_texture_id(param, "ambient filter")) + { + material.ambient_filter_texture_id() = *texture_id; + material.component_flags |= material_components::flags::ambient_filter_texture; + } + + return codes::ok; + }), + ztu::make_line_parser("map_Kd ", ztu::is_not_repeating, [&](const auto& param) + { + if (const auto texture_id = fetch_texture_id(param, "diffuse filter")) + { + material.diffuse_filter_texture_id() = *texture_id; + material.component_flags |= material_components::flags::diffuse_filter_texture; + } + + return codes::ok; + }), + ztu::make_line_parser("map_Ks ", ztu::is_not_repeating, [&](const auto& param) + { + if (const auto texture_id = fetch_texture_id(param, "specular filter")) + { + material.specular_filter_texture_id() = *texture_id; + material.component_flags |= material_components::flags::specular_filter_texture; + } + + return codes::ok; + }), + ztu::make_line_parser("map_Ns ", ztu::is_not_repeating, [&](const auto& param) + { + if (const auto texture_id = fetch_texture_id(param, "shininess")) + { + material.shininess_texture_id() = *texture_id; + material.component_flags |= material_components::flags::shininess_texture; + } + + return codes::ok; + }), + ztu::make_line_parser("map_d ", ztu::is_not_repeating, [&](const auto& param) + { + if (const auto texture_id = fetch_texture_id(param, "alpha")) + { + material.alpha_texture_id() = *texture_id; + material.component_flags |= material_components::flags::alpha_texture; + } + + return codes::ok; + }), + ztu::make_line_parser("bump ", ztu::is_not_repeating, [&](const auto& param) + { + if (const auto texture_id = fetch_texture_id(param, "bump")) + { + material.bump_texture_id() = *texture_id; + material.component_flags |= material_components::flags::bump_texture; + } + + return codes::ok; + }) + ); + + if (ec != codes::ok) + { + const auto e = make_error_code(ec); + ztu::logger::error("Error while parsing mtl file %: %", filename, e.message()); + } + + push_material(); +} + +std::optional assets::mtl_parser::parser_context::fetch_texture_id( + const std::filesystem::path& mtl_dir, + std::string_view filename, + std::string_view texture_type_name +) { + auto texture_filename = std::filesystem::path(filename); + if (texture_filename.is_relative()) + { + texture_filename = mtl_dir / texture_filename; + } + + const auto texture_id_it = m_texture_id_lookup->find(texture_filename); + if (texture_id_it == m_texture_id_lookup->end()) + { + ztu::logger::warn( + "%-texture at % has not been registered and can therefor not be used.", + texture_type_name, + texture_filename + ); + return std::nullopt; + } + + return texture_id_it->second; +} + + + template std::errc parse_numeric_vector(std::string_view param, std::array& values) { - auto it = param.begin(), end = param.end(); + const auto end = param.end(); + auto it = param.begin(); for (auto& value : values) { @@ -90,7 +423,9 @@ std::errc parse_numeric_vector(std::string_view param, std::array& val }; -void mtl_loader::find_textures( + + +void assets::mtl_parser::find_textures( std::span buffer, std::filesystem::path& path_buffer, const std::filesystem::path& base_directory, @@ -230,356 +565,3 @@ void mtl_loader::find_textures( } } while (not in.eof()); } - -std::error_code mtl_loader::prefetch( - const file_dir_list& paths, - prefetch_queue& queue -) { - namespace fs = std::filesystem; - using mtl_loader_error::codes; - using mtl_loader_error::make_error_code; - - auto buffer = std::vector(8 * 1024, '\0'); - - auto in = std::ifstream{}; - - auto path_buffer = fs::path{}; - auto filename_buffer = fs::path{}; - - const auto process_file = [&]() - { - in.open(filename_buffer); - if (not in.is_open()) { - ztu::logger::error("Could not open .mtl file '%'", filename_buffer); - return; - } - - filename_buffer.remove_filename(); - - find_textures(buffer, path_buffer, filename_buffer, in, queue.texture.files); - - in.close(); - }; - - - for (const auto file : paths.files) - { - filename_buffer.assign(file); - process_file(); - } - - for (const auto directory : paths.directories) - { - for (const auto& file : fs::directory_iterator{ directory }) { - - filename_buffer.assign(file.path()); - - // Avoid heap allocation of .extension() - if (not std::string_view(filename_buffer.c_str()).ends_with(".obj")) - { - continue; - } - - process_file(); - } - } - - return {}; -} - -std::error_code mtl_loader::load_directory( - dynamic_data_loader_ctx& ctx, - dynamic_material_store& store, - material_components::flags enabled_components, - const std::filesystem::path& path, - const bool pedantic -) { - namespace fs = std::filesystem; - - if (not fs::exists(path)) - { - return make_error_code(std::errc::no_such_file_or_directory); - } - - for (const auto& file : fs::directory_iterator{ path }) - { - const auto& file_path = file.path(); - - if (file_path.extension() != ".obj") - { - continue; - } - - if (const auto e = load( - ctx, - store, - enabled_components, - path, - pedantic - )) { - ztu::logger::error( - "Error while loading obj file '%': [%] %", - file_path, - e.category().name(), - e.message() - ); - } - } - - return {}; -} - -std::error_code mtl_loader::load( - dynamic_data_loader_ctx& ctx, - dynamic_material_store& store, - material_components::flags enabled_components, - const std::filesystem::path& filename, - const bool pedantic -) { - using mtl_loader_error::codes; - using mtl_loader_error::make_error_code; - - using flags = material_components::flags; - - const auto component_disabled = [&](const material_components::flags component) { - return (enabled_components & component) == flags::none; - }; - - // TODO unroll stuff - const auto textures_disabled = component_disabled(flags::ambient_filter_texture); - const auto surface_properties_disabled = component_disabled(flags::surface_properties); - const auto transparencies_disabled = component_disabled(flags::transparency); - - auto in = std::ifstream{ filename }; - if (not in.is_open()) { - return make_error_code(codes::cannot_open_file); - } - - namespace fs = std::filesystem; - const auto directory = fs::canonical(fs::path(filename).parent_path()); - - auto name = std::string{}; - auto material = dynamic_material_data{}; - - const auto push_material = [&]() - { - if (not name.empty()) - { - const auto id = store.add(std::move(material)); - m_id_lookup.emplace(std::move(name), id); - } - name = std::string{}; - material = dynamic_material_data{}; - }; - - const auto load_texture = [&]( - const std::string_view path, - std::string_view texture_type_name, - auto&& f - ) { - auto texture_filename = fs::path(path); - if (texture_filename.is_relative()) - { - texture_filename = directory / texture_filename; - } - - const auto extension = texture_filename.extension().string(); - - auto texture_type = std::string_view{ extension }; - if (not texture_type.empty() and texture_type.front() == '.') - { - texture_type = texture_type.substr(1); - } - - if (const auto loader_id = ctx.texture_loader.find_loader(texture_type)) - { - if (auto res = ctx.texture_loader.read( - ctx, - *loader_id, - texture_filename, - pedantic - )) { - f(*res); - } - else - { - const auto error = res.error(); - ztu::logger::warn( - "Error while loading % texture '%': [%] %", - texture_type_name, - path, - error.category().name(), - error.message() - ); - } - } - else - { - ztu::logger::warn( - "Failed to load % texture '%' because extension is not supported.", - texture_type_name, - path - ); - } - }; - - const auto ec = ztu::parse_lines( - in, - pedantic, - ztu::make_line_parser("newmtl ", ztu::is_not_repeating, [&](const auto& param) - { - push_material(); - name = param; - - return codes::ok; - }), - ztu::make_line_parser("Ka ", ztu::is_not_repeating, [&](const auto& param) - { - material_components::ambient_filter ambient_filter; - if (parse_numeric_vector(param, ambient_filter) != std::errc{}) [[unlikely]] - { - return codes::malformed_ambient_color; // TODO rename to filter - } - - material.ambient_filter = mbient_filter; - material.components() |= flags::ambient_filter; - - return codes::ok; - }), - ztu::make_line_parser("Kd ", ztu::is_not_repeating, [&](const auto& param) - { - if (surface_properties_disabled) return codes::ok; - - auto& properties = material.initialized_surface_properties(); - if (parse_numeric_vector(param, properties.diffuse_filter) != std::errc{}) [[unlikely]] - { - return codes::malformed_diffuse_color; - } - - material.components() |= flags::surface_properties; - - return codes::ok; - }), - ztu::make_line_parser("Ks ", ztu::is_not_repeating, [&](const auto& param) - { - if (surface_properties_disabled) return codes::ok; - - auto& properties = material.initialized_surface_properties(); - if (parse_numeric_vector(param, properties.specular_filter) != std::errc{}) [[unlikely]] - { - return codes::malformed_specular_color; - } - - material.components() |= flags::surface_properties; - - return codes::ok; - }), - ztu::make_line_parser("Ns ", ztu::is_not_repeating, [&](const auto& param) - { - if (surface_properties_disabled) return codes::ok; - - auto& properties = material.initialized_surface_properties(); - std::array shininess{}; - if (parse_numeric_vector(param, shininess) != std::errc{}) [[unlikely]] - { - return codes::malformed_specular_exponent; - } - - properties.shininess = shininess.front(); - material.components() |= flags::surface_properties; - - return codes::ok; - }), - ztu::make_line_parser("d ", ztu::is_not_repeating, [&](const auto& param) - { - if (transparencies_disabled) return codes::ok; - - std::array transparency{}; - if (parse_numeric_vector(param, transparency) != std::errc{}) [[unlikely]] - { - return codes::malformed_dissolve; - } - - material.transparency().emplace(transparency.front()); - material.components() |= flags::transparency; - - return codes::ok; - }), - ztu::make_line_parser("map_Ka ", ztu::is_not_repeating, [&](const auto& param) - { - if (textures_disabled) return codes::ok; - - load_texture(param, "ambient color", [&](const auto id) { - material.specular_filter_texture_id() = id; - material.components() |= flags::ambient_filter_texture; - }); - - return codes::ok; - }), - ztu::make_line_parser("map_Kd ", ztu::is_not_repeating, [&](const auto& param) - { - if (textures_disabled) return codes::ok; - - load_texture(param, "diffuse color", [&](const auto id) { - material.diffuse_filter_texture_id() = id; - material.components() |= flags::diffuse_filter_texture; - }); - - return codes::ok; - }), - ztu::make_line_parser("map_Ks ", ztu::is_not_repeating, [&](const auto& param) - { - if (textures_disabled) return codes::ok; - - load_texture(param, "specular color", [&](const auto id) { - material.specular_filter_texture_id() = id; - material.components() |= flags::specular_filter_texture; - }); - - return codes::ok; - }), - ztu::make_line_parser("map_Ns ", ztu::is_not_repeating, [&](const auto& param) - { - if (textures_disabled) return codes::ok; - - load_texture(param, "shininess", [&](const auto id) { - material.shininess_texture_id() = id; - material.components() |= flags::shininess_texture; - }); - - return codes::ok; - }), - ztu::make_line_parser("map_d ", ztu::is_not_repeating, [&](const auto& param) - { - if (textures_disabled) return codes::ok; - - load_texture(param, "alpha", [&](const auto id) { - material.alpha_texture_id() = id; - material.components() |= flags::alpha_texture; - }); - - return codes::ok; - }), - ztu::make_line_parser("bump ", ztu::is_not_repeating, [&](const auto& param) - { - if (textures_disabled) return codes::ok; - - load_texture(param, "bump", [&](const auto id) { - material.bump_texture_id() = id; - material.components() |= flags::bump_texture; - }); - - return codes::ok; - }) - ); - - if (ec != codes::ok) - { - return make_error_code(ec); - } - - push_material(); - - return {}; -} - diff --git a/source/opengl/data_managers/shader_source_manager.cpp b/source/opengl/data_managers/shader_source_manager.cpp index 7246f0d..9e7b2b2 100644 --- a/source/opengl/data_managers/shader_source_manager.cpp +++ b/source/opengl/data_managers/shader_source_manager.cpp @@ -68,28 +68,21 @@ void zgl::shader_source_manager::process(const store_type& shader_sources) for (const auto& [ id, shader_source ] : shader_sources) { - const auto meta = metadata_type{ - .stage = shader_source.stage, - .components = shader_source.components, - .static_enable = shader_source.static_enable, - .dynamic_enable = shader_source.dynamic_enable - }; - // Sorted insert should be faster than std::sort and std::unique // for small numbers of elements and high numbers of duplicates. const auto it = std::ranges::upper_bound( m_shader_source_lookup, - meta, + shader_source.meta, prioritized_metadata_comparator{}, &entry_type::first ); - if (it != m_shader_source_lookup.end() and it->first == meta) + if (it != m_shader_source_lookup.end() and it->first == shader_source.meta) { continue; } - m_shader_source_lookup.emplace(it, meta, id); + m_shader_source_lookup.emplace(it, shader_source.meta, id); } } @@ -132,7 +125,7 @@ void zgl::shader_source_manager::fetch( while ( source_it != m_shader_source_lookup.end() and - source_it->first.geometry == req.geometry_type and + source_it->first.geometry_type == req.geometry_type and source_it->first.stage == req.stage ) { const auto& [ meta, id ] = *source_it; @@ -146,7 +139,7 @@ void zgl::shader_source_manager::fetch( to_be_enabled = req.components & meta.static_enable; source_id = id; - res.static_enabled = meta.commponents & ~meta.dynamic_enable & ~unwanted_components; + res.static_enabled = meta.components & ~meta.dynamic_enable & ~unwanted_components; res.dynamic_enable = meta.dynamic_enable; break;