Made assets::data_stores thread safe.
This commit is contained in:
@@ -2,17 +2,17 @@
|
||||
# error Never include this file directly include 'material_data.hpp'
|
||||
#endif
|
||||
|
||||
inline std::optional<assets::material_components::ambient_filter>& assets::material_data::specular_filter()
|
||||
inline std::optional<assets::material_components::specular_filter>& assets::material_data::specular_filter()
|
||||
{
|
||||
return std::get<material_components::indices::ambient_filter>(components);
|
||||
return std::get<material_components::indices::specular_filter>(components);
|
||||
}
|
||||
inline std::optional<assets::material_components::diffuse_filter>& assets::material_data::diffuse_filter()
|
||||
{
|
||||
return std::get<material_components::indices::diffuse_filter>(components);
|
||||
}
|
||||
inline std::optional<assets::material_components::specular_filter>& assets::material_data::specular_filter()
|
||||
inline std::optional<assets::material_components::ambient_filter>& assets::material_data::ambient_filter()
|
||||
{
|
||||
return std::get<material_components::indices::specular_filter>(components);
|
||||
return std::get<material_components::indices::ambient_filter>(components);
|
||||
}
|
||||
inline std::optional<assets::material_components::shininess>& assets::material_data::shininess()
|
||||
{
|
||||
@@ -23,17 +23,17 @@ inline std::optional<assets::material_components::alpha>& assets::material_data:
|
||||
return std::get<material_components::indices::alpha>(components);
|
||||
}
|
||||
|
||||
inline std::optional<assets::material_components::ambient_filter_texture>& assets::material_data::specular_filter_texture_id()
|
||||
inline std::optional<assets::material_components::specular_filter_texture>& assets::material_data::specular_filter_texture_id()
|
||||
{
|
||||
return std::get<material_components::indices::ambient_filter_texture>(components);
|
||||
return std::get<material_components::indices::specular_filter_texture>(components);
|
||||
}
|
||||
inline std::optional<assets::material_components::diffuse_filter_texture>& assets::material_data::diffuse_filter_texture_id()
|
||||
{
|
||||
return std::get<material_components::indices::diffuse_filter_texture>(components);
|
||||
}
|
||||
inline std::optional<assets::material_components::specular_filter_texture>& assets::material_data::specular_filter_texture_id()
|
||||
inline std::optional<assets::material_components::ambient_filter_texture>& assets::material_data::ambient_filter_texture_id()
|
||||
{
|
||||
return std::get<material_components::indices::specular_filter_texture>(components);
|
||||
return std::get<material_components::indices::ambient_filter_texture>(components);
|
||||
}
|
||||
inline std::optional<assets::material_components::shininess_texture>& assets::material_data::shininess_texture_id()
|
||||
{
|
||||
@@ -48,17 +48,17 @@ inline std::optional<assets::material_components::bump_texture>& assets::materia
|
||||
return std::get<material_components::indices::bump_texture(components);
|
||||
}
|
||||
|
||||
inline const std::optional<assets::material_components::ambient_filter>& assets::material_data::specular_filter() const
|
||||
inline const std::optional<assets::material_components::specular_filter>& assets::material_data::specular_filter() const
|
||||
{
|
||||
return std::get<material_components::indices::ambient_filter>(components);
|
||||
return std::get<material_components::indices::specular_filter>(components);
|
||||
}
|
||||
inline const std::optional<assets::material_components::diffuse_filter>& assets::material_data::diffuse_filter() const
|
||||
{
|
||||
return std::get<material_components::indices::diffuse_filter>(components);
|
||||
}
|
||||
inline const std::optional<assets::material_components::specular_filter>& assets::material_data::specular_filter() const
|
||||
inline const std::optional<assets::material_components::ambient_filter>& assets::material_data::ambient_filter() const
|
||||
{
|
||||
return std::get<material_components::indices::specular_filter>(components);
|
||||
return std::get<material_components::indices::ambient_filter>(components);
|
||||
}
|
||||
inline const std::optional<assets::material_components::shininess>& assets::material_data::shininess() const
|
||||
{
|
||||
@@ -69,9 +69,9 @@ inline const std::optional<assets::material_components::alpha>& assets::material
|
||||
return std::get<material_components::indices::alpha>(components);
|
||||
}
|
||||
|
||||
inline const std::optional<assets::material_components::ambient_filter_texture>& assets::material_data::specular_filter_texture_id() const
|
||||
inline const std::optional<assets::material_components::specular_filter_texture>& assets::material_data::specular_filter_texture_id() const
|
||||
{
|
||||
return std::get<material_components::indices::ambient_filter_texture>(components);
|
||||
return std::get<material_components::indices::specular_filter_texture>(components);
|
||||
}
|
||||
|
||||
inline const std::optional<assets::material_components::diffuse_filter_texture>& assets::material_data::diffuse_filter_texture_id() const
|
||||
@@ -79,9 +79,9 @@ inline const std::optional<assets::material_components::diffuse_filter_texture>&
|
||||
return std::get<material_components::indices::diffuse_filter_texture>(components);
|
||||
}
|
||||
|
||||
inline const std::optional<assets::material_components::specular_filter_texture>& assets::material_data::specular_filter_texture_id() const
|
||||
inline const std::optional<assets::material_components::ambient_filter_texture>& assets::material_data::ambient_filter_texture_id() const
|
||||
{
|
||||
return std::get<material_components::indices::specular_filter_texture>(components);
|
||||
return std::get<material_components::indices::ambient_filter_texture>(components);
|
||||
}
|
||||
|
||||
inline const std::optional<assets::material_components::shininess_texture>& assets::material_data::shininess_texture_id() const
|
||||
|
||||
@@ -3,61 +3,288 @@
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <mutex>
|
||||
|
||||
template<typename T>
|
||||
typename generic_basic_store<T>::id_type generic_basic_store<T>::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<typename ID, typename T>
|
||||
assets::detail::generic_basic_store_iterator<ID, T>::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 ID, typename T>
|
||||
typename assets::detail::generic_basic_store_iterator<ID, T>::reference assets::detail::generic_basic_store_iterator<ID, T>::operator*() const {
|
||||
return dereference();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::pair<typename generic_basic_store<T>::iterator_type, bool> generic_basic_store<T>::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<typename ID, typename T>
|
||||
assets::detail::generic_basic_store_iterator<ID, T>& assets::detail::generic_basic_store_iterator<ID, T>::operator++() {
|
||||
++m_index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::pair<typename generic_basic_store<T>::const_iterator, bool> generic_basic_store<T>::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<typename ID, typename T>
|
||||
assets::detail::generic_basic_store_iterator<ID, T> assets::detail::generic_basic_store_iterator<ID, T>::operator++(int) {
|
||||
generic_basic_store_iterator tmp = *this;
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void generic_basic_store<T>::remove(iterator_type it)
|
||||
template<typename ID, typename T>
|
||||
assets::detail::generic_basic_store_iterator<ID, T>& assets::detail::generic_basic_store_iterator<ID, T>::operator--() {
|
||||
--m_index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename ID, typename T>
|
||||
assets::detail::generic_basic_store_iterator<ID, T> assets::detail::generic_basic_store_iterator<ID, T>::operator--(int) {
|
||||
auto tmp = *this;
|
||||
--(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template<typename ID, typename T>
|
||||
assets::detail::generic_basic_store_iterator<ID, T>& assets::detail::generic_basic_store_iterator<ID, T>::operator+=(const difference_type n)
|
||||
{
|
||||
const auto index = it - m_data.begin();
|
||||
m_data.erase(it);
|
||||
m_index += n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename ID, typename T>
|
||||
assets::detail::generic_basic_store_iterator<ID, T>& assets::detail::generic_basic_store_iterator<ID, T>::operator-=(const difference_type n)
|
||||
{
|
||||
return (*this) += -n;
|
||||
}
|
||||
|
||||
template<typename ID, typename T>
|
||||
assets::detail::generic_basic_store_iterator<ID, T> assets::detail::generic_basic_store_iterator<ID, T>::operator+(const difference_type n) const
|
||||
{
|
||||
auto tmp = *this;
|
||||
return tmp += n; // TODO clion says n is unused
|
||||
}
|
||||
|
||||
template<typename ID, typename T>
|
||||
assets::detail::generic_basic_store_iterator<ID, T> assets::detail::generic_basic_store_iterator<ID, T>::operator-(const difference_type n) const
|
||||
{
|
||||
auto tmp = *this;
|
||||
return tmp -= n; // TODO clion says n is unused
|
||||
}
|
||||
|
||||
template<typename ID, typename T>
|
||||
typename assets::detail::generic_basic_store_iterator<ID, T>::difference_type
|
||||
assets::detail::generic_basic_store_iterator<ID, T>::operator-(const generic_basic_store_iterator& other) const
|
||||
{
|
||||
return static_cast<difference_type>(m_index) - static_cast<difference_type>(other.m_index);
|
||||
}
|
||||
|
||||
template<typename ID, typename T>
|
||||
typename assets::detail::generic_basic_store_iterator<ID, T>::reference assets::detail::generic_basic_store_iterator<ID, T>::operator[](
|
||||
const difference_type n
|
||||
) const {
|
||||
return *(*this + n);
|
||||
}
|
||||
|
||||
template<typename ID, typename T>
|
||||
bool assets::detail::generic_basic_store_iterator<ID, T>::operator==(const generic_basic_store_iterator& other) const
|
||||
{
|
||||
return m_ids == other.m_ids and m_index == other.m_index;
|
||||
}
|
||||
|
||||
template<typename ID, typename T>
|
||||
bool assets::detail::generic_basic_store_iterator<ID, T>::operator!=(const generic_basic_store_iterator& other) const
|
||||
{
|
||||
return not (*this == other);
|
||||
}
|
||||
|
||||
template<typename ID, typename T>
|
||||
bool assets::detail::generic_basic_store_iterator<ID, T>::operator<(const generic_basic_store_iterator& other) const
|
||||
{
|
||||
return m_index < other.m_index;
|
||||
}
|
||||
|
||||
template<typename ID, typename T>
|
||||
bool assets::detail::generic_basic_store_iterator<ID, T>::operator<=(const generic_basic_store_iterator& other) const
|
||||
{
|
||||
return m_index <= other.m_index;
|
||||
}
|
||||
|
||||
template<typename ID, typename T>
|
||||
bool assets::detail::generic_basic_store_iterator<ID, T>::operator>(const generic_basic_store_iterator& other) const
|
||||
{
|
||||
return m_index > other.m_index;
|
||||
}
|
||||
|
||||
template<typename ID, typename T>
|
||||
bool assets::detail::generic_basic_store_iterator<ID, T>::operator>=(const generic_basic_store_iterator& other) const
|
||||
{
|
||||
return m_index >= other.m_index;
|
||||
}
|
||||
|
||||
template<typename ID, typename T>
|
||||
typename assets::detail::generic_basic_store_iterator<ID, T>::reference
|
||||
assets::detail::generic_basic_store_iterator<ID, T>::dereference() const
|
||||
{
|
||||
return {
|
||||
m_ids[m_index],
|
||||
m_data[m_index]
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
template<typename ID, typename T>
|
||||
bool assets::detail::generic_basic_store<ID, T>::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<typename ID, typename T>
|
||||
bool assets::detail::generic_basic_store<ID, T>::insert(iterator it, const ID id, const T& data)
|
||||
{
|
||||
auto lock = std::unique_lock{ m_mutex };
|
||||
|
||||
return unsafe_insert(it, id, data);
|
||||
}
|
||||
|
||||
template<typename ID, typename T>
|
||||
std::pair<typename assets::detail::generic_basic_store<ID, T>::iterator, bool> assets::detail::generic_basic_store<ID, T>::find(ID id)
|
||||
{
|
||||
auto lock = std::shared_lock{ m_mutex };
|
||||
|
||||
return unsafe_find(id);
|
||||
}
|
||||
|
||||
template<typename ID, typename T>
|
||||
std::pair<typename assets::detail::generic_basic_store<ID, T>::const_iterator, bool> assets::detail::generic_basic_store<ID, T>::find(ID id) const
|
||||
{
|
||||
auto lock = std::shared_lock{ m_mutex };
|
||||
|
||||
return unsafe_find(id);
|
||||
}
|
||||
|
||||
template<typename ID, typename T>
|
||||
bool assets::detail::generic_basic_store<ID, T>::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<typename ID, typename T>
|
||||
std::pair<typename assets::detail::generic_basic_store<ID, T>::iterator, bool> assets::detail::generic_basic_store<ID, T>::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<typename ID, typename T>
|
||||
std::pair<typename assets::detail::generic_basic_store<ID, T>::const_iterator, bool> assets::detail::generic_basic_store<ID, T>::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<typename ID, typename T>
|
||||
void assets::detail::generic_basic_store<ID, T>::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<typename T>
|
||||
void generic_basic_store<T>::clear()
|
||||
template<typename ID, typename T>
|
||||
void assets::detail::generic_basic_store<ID, T>::clear()
|
||||
{
|
||||
auto lock = std::unique_lock{ m_mutex };
|
||||
m_data.clear();
|
||||
m_ids.clear();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::span<T> generic_basic_store<T>::data()
|
||||
{
|
||||
return m_data;
|
||||
template<typename ID, typename T>
|
||||
std::shared_lock<std::shared_mutex> assets::detail::generic_basic_store<ID, T>::acquire_read_lock() const {
|
||||
return std::shared_lock{ m_mutex };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::span<const T> generic_basic_store<T>::data() const
|
||||
{
|
||||
return m_data;
|
||||
template<typename ID, typename T>
|
||||
std::unique_lock<std::shared_mutex> assets::detail::generic_basic_store<ID, T>::acquire_write_lock() {
|
||||
return std::unique_lock{ m_mutex };
|
||||
}
|
||||
|
||||
template<typename ID, typename T>
|
||||
typename assets::detail::generic_basic_store<ID, T>::iterator assets::detail::generic_basic_store<ID, T>::begin()
|
||||
{
|
||||
return iterator{
|
||||
m_ids.data(),
|
||||
m_data.begin(),
|
||||
0
|
||||
};
|
||||
}
|
||||
|
||||
template<typename ID, typename T>
|
||||
typename assets::detail::generic_basic_store<ID, T>::iterator assets::detail::generic_basic_store<ID, T>::end()
|
||||
{
|
||||
return iterator{
|
||||
m_ids.data(),
|
||||
m_data.begin(),
|
||||
m_ids.size()
|
||||
};
|
||||
}
|
||||
|
||||
template<typename ID, typename T>
|
||||
typename assets::detail::generic_basic_store<ID, T>::const_iterator assets::detail::generic_basic_store<ID, T>::begin() const
|
||||
{
|
||||
return const_iterator{
|
||||
m_ids.data(),
|
||||
m_data.begin(),
|
||||
0
|
||||
};
|
||||
}
|
||||
|
||||
template<typename ID, typename T>
|
||||
typename assets::detail::generic_basic_store<ID, T>::const_iterator assets::detail::generic_basic_store<ID, T>::end() const
|
||||
{
|
||||
return const_iterator{
|
||||
m_ids.data(),
|
||||
m_data.begin(),
|
||||
m_ids.size()
|
||||
};
|
||||
}
|
||||
|
||||
template<typename ID, typename T>
|
||||
typename assets::detail::generic_basic_store<ID, T>::const_iterator assets::detail::generic_basic_store<ID, T>::cbegin() const
|
||||
{
|
||||
return this->begin();
|
||||
}
|
||||
|
||||
template<typename ID, typename T>
|
||||
typename assets::detail::generic_basic_store<ID, T>::const_iterator assets::detail::generic_basic_store<ID, T>::cend() const
|
||||
{
|
||||
return this->end();
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
#include <span>
|
||||
#include <mutex>
|
||||
#include <tuple>
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
@@ -14,7 +14,7 @@ assets::detail::generic_material_store_iterator<Ts...>::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<Ts...>::dereference(std::index_s
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
std::tuple<std::add_pointer_t<Ts>...> assets::detail::generic_material_store<Ts...>::component_iterators()
|
||||
std::tuple<std::add_pointer_t<Ts>...> assets::detail::generic_material_store<z3d::structure<Ts...>>::component_iterators()
|
||||
{
|
||||
return [&]<auto... Is>(std::index_sequence<Is>)
|
||||
{
|
||||
@@ -205,7 +205,7 @@ std::tuple<std::add_pointer_t<Ts>...> assets::detail::generic_material_store<Ts.
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
std::tuple<std::add_pointer_t<std::add_const_t<Ts>>...> assets::detail::generic_material_store<Ts...>::component_iterators() const
|
||||
std::tuple<std::add_pointer_t<std::add_const_t<Ts>>...> assets::detail::generic_material_store<z3d::structure<Ts...>>::component_iterators() const
|
||||
{
|
||||
return [&]<auto... Is>(std::index_sequence<Is>)
|
||||
{
|
||||
@@ -215,8 +215,8 @@ std::tuple<std::add_pointer_t<std::add_const_t<Ts>>...> assets::detail::generic_
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
std::array<typename assets::detail::generic_material_store<Ts...>::count_type, 1 + sizeof...(Ts)>
|
||||
assets::detail::generic_material_store<Ts...>::array_counts() const
|
||||
std::array<typename assets::detail::generic_material_store<z3d::structure<Ts...>>::count_type, 1 + sizeof...(Ts)>
|
||||
assets::detail::generic_material_store<z3d::structure<Ts...>>::array_counts() const
|
||||
{
|
||||
return [&]<auto... Is>(std::index_sequence<Is>)
|
||||
{
|
||||
@@ -228,84 +228,139 @@ assets::detail::generic_material_store<Ts...>::array_counts() const
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_material_store<Ts...>::id_type assets::detail::generic_material_store<Ts...>::add(
|
||||
const component_set& material
|
||||
) {
|
||||
bool assets::detail::generic_material_store<z3d::structure<Ts...>>::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<typename... Ts>
|
||||
bool assets::detail::generic_material_store<z3d::structure<Ts...>>::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<typename... Ts>
|
||||
std::pair<typename assets::detail::generic_material_store<z3d::structure<Ts...>>::iterator, bool> assets::detail::generic_material_store<z3d::structure<Ts...>>::find(id_type id)
|
||||
{
|
||||
auto lock = std::shared_lock{ m_mutex };
|
||||
|
||||
return unsafe_find(id);
|
||||
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
std::pair<typename assets::detail::generic_material_store<z3d::structure<Ts...>>::const_iterator, bool> assets::detail::generic_material_store<z3d::structure<Ts...>>::find(id_type id) const
|
||||
{
|
||||
auto lock = std::shared_lock{ m_mutex };
|
||||
|
||||
return unsafe_find(id);
|
||||
}
|
||||
|
||||
|
||||
template<typename... Ts>
|
||||
bool assets::detail::generic_material_store<z3d::structure<Ts...>>::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];
|
||||
|
||||
[&]<auto... Is>(std::integer_sequence<Is...>)
|
||||
{
|
||||
if (const auto& component_opt = std::get<Is>(material.data))
|
||||
const auto is_component_enabled = src_component_flags & component_flag_type{ 1 } << Is;
|
||||
const auto was_component_enabled = (
|
||||
new_entry
|
||||
? static_cast<bool>(dst_component_flags & component_flag_type{ 1 } << Is)
|
||||
: component_flag_type{}
|
||||
);
|
||||
|
||||
const auto& src_component = std::get<Is>(data.components);
|
||||
auto& dst_component_array = std::get<Is>(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<Is>(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<Ts...>{});
|
||||
|
||||
m_component_flag_counts.push_back(component_flags);
|
||||
dst_component_flags = src_component_flags;
|
||||
|
||||
return id;
|
||||
return new_entry;
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
std::pair<typename assets::detail::generic_material_store<Ts...>::iterator_type, bool> assets::detail::generic_material_store<Ts...>::find(id_type id)
|
||||
std::pair<typename assets::detail::generic_material_store<z3d::structure<Ts...>>::iterator, bool> assets::detail::generic_material_store<z3d::structure<Ts...>>::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<typename... Ts>
|
||||
std::pair<typename assets::detail::generic_material_store<Ts...>::const_iterator, bool> assets::detail::generic_material_store<Ts...>::find(id_type id) const
|
||||
std::pair<typename assets::detail::generic_material_store<z3d::structure<Ts...>>::const_iterator, bool> assets::detail::generic_material_store<z3d::structure<Ts...>>::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<typename... Ts>
|
||||
void assets::detail::generic_material_store<Ts...>::remove(const iterator_type& it)
|
||||
void assets::detail::generic_material_store<z3d::structure<Ts...>>::remove(const iterator& it)
|
||||
{
|
||||
auto lock = std::unique_lock{ m_mutex };
|
||||
|
||||
m_ids.erase(m_ids.begin() + it.m_index);
|
||||
|
||||
return [&]<auto... Is>(std::index_sequence<Is>)
|
||||
{
|
||||
auto& component_vector = std::get<Is>(m_component_arrays);
|
||||
(component_vector.erase(component_vector.begin() + it.m_offsets[Is]), ...);
|
||||
auto& component_array = std::get<Is>(m_component_arrays);
|
||||
(component_array.erase(component_array.begin() + it.m_offsets[Is]), ...);
|
||||
} (std::index_sequence_for<Ts...>{});
|
||||
|
||||
m_component_flag_counts.erase(m_component_flag_counts.begin() + it.m_index);
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
void assets::detail::generic_material_store<Ts...>::clear()
|
||||
void assets::detail::generic_material_store<z3d::structure<Ts...>>::clear()
|
||||
{
|
||||
auto lock = std::unique_lock{ m_mutex };
|
||||
|
||||
m_ids.clear();
|
||||
[&]<auto... Is>(std::index_sequence<Is>)
|
||||
{
|
||||
@@ -315,9 +370,19 @@ void assets::detail::generic_material_store<Ts...>::clear()
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_material_store<Ts...>::iterator_type assets::detail::generic_material_store<Ts...>::begin()
|
||||
std::shared_lock<std::shared_mutex> assets::detail::generic_material_store<z3d::structure<Ts...>>::acquire_read_lock() const {
|
||||
return std::shared_lock{ m_mutex };
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
std::unique_lock<std::shared_mutex> assets::detail::generic_material_store<z3d::structure<Ts...>>::acquire_write_lock() {
|
||||
return std::unique_lock{ m_mutex };
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_material_store<z3d::structure<Ts...>>::iterator assets::detail::generic_material_store<z3d::structure<Ts...>>::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<Ts...>::iterator_type assets::de
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_material_store<Ts...>::iterator_type assets::detail::generic_material_store<Ts...>::end()
|
||||
typename assets::detail::generic_material_store<z3d::structure<Ts...>>::iterator assets::detail::generic_material_store<z3d::structure<Ts...>>::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<Ts...>::iterator_type assets::de
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_material_store<Ts...>::const_iterator assets::detail::generic_material_store<Ts...>::begin() const
|
||||
typename assets::detail::generic_material_store<z3d::structure<Ts...>>::const_iterator assets::detail::generic_material_store<z3d::structure<Ts...>>::begin() const
|
||||
{
|
||||
return const_iterator{
|
||||
m_ids.data(),
|
||||
@@ -351,7 +416,7 @@ typename assets::detail::generic_material_store<Ts...>::const_iterator assets::d
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_material_store<Ts...>::const_iterator assets::detail::generic_material_store<Ts...>::end() const
|
||||
typename assets::detail::generic_material_store<z3d::structure<Ts...>>::const_iterator assets::detail::generic_material_store<z3d::structure<Ts...>>::end() const
|
||||
{
|
||||
return const_iterator{
|
||||
m_ids.data(),
|
||||
@@ -363,24 +428,13 @@ typename assets::detail::generic_material_store<Ts...>::const_iterator assets::d
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_material_store<Ts...>::const_iterator assets::detail::generic_material_store<Ts...>::cbegin() const
|
||||
typename assets::detail::generic_material_store<z3d::structure<Ts...>>::const_iterator assets::detail::generic_material_store<z3d::structure<Ts...>>::cbegin() const
|
||||
{
|
||||
return const_cast<const generic_material_store*>(this)->begin();
|
||||
return this->begin();
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_material_store<Ts...>::const_iterator assets::detail::generic_material_store<Ts...>::cend() const
|
||||
typename assets::detail::generic_material_store<z3d::structure<Ts...>>::const_iterator assets::detail::generic_material_store<z3d::structure<Ts...>>::cend() const
|
||||
{
|
||||
return const_cast<const generic_material_store*>(this)->end();
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_material_store<Ts...>::view_type assets::detail::generic_material_store<Ts...>::view()
|
||||
{
|
||||
return { begin(), end() };
|
||||
}
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_material_store<Ts...>::const_view_type assets::detail::generic_material_store<Ts...>::view() const
|
||||
{
|
||||
return { begin(), end() };
|
||||
return this->end();
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include <algorithm>
|
||||
#include <mutex>
|
||||
#include "util/vector_replace_range.hpp"
|
||||
|
||||
template<typename... Ts>
|
||||
assets::detail::generic_mesh_store_iterator<Ts...>::generic_mesh_store_iterator(
|
||||
@@ -16,7 +18,7 @@ assets::detail::generic_mesh_store_iterator<Ts...>::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<Ts...>::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<Is>(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<std::size_t... Is>
|
||||
typename assets::detail::generic_mesh_store_iterator<Ts...>::reference
|
||||
assets::detail::generic_mesh_store_iterator<Ts...>::dereference(std::index_sequence<Is...>) 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<Ts...>::dereference(std::index_seque
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
std::tuple<std::add_pointer_t<Ts>...> assets::detail::generic_mesh_store<Ts...>::component_iterators()
|
||||
std::tuple<std::add_pointer_t<Ts>...> assets::detail::generic_mesh_store<z3d::structure<Ts...>>::component_iterators()
|
||||
{
|
||||
return [&]<auto... Is>(std::index_sequence<Is>)
|
||||
{
|
||||
@@ -215,7 +217,7 @@ std::tuple<std::add_pointer_t<Ts>...> assets::detail::generic_mesh_store<Ts...>:
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
std::tuple<std::add_pointer_t<std::add_const_t<Ts>>...> assets::detail::generic_mesh_store<Ts...>::component_iterators() const
|
||||
std::tuple<std::add_pointer_t<std::add_const_t<Ts>>...> assets::detail::generic_mesh_store<z3d::structure<Ts...>>::component_iterators() const
|
||||
{
|
||||
return [&]<auto... Is>(std::index_sequence<Is>)
|
||||
{
|
||||
@@ -225,13 +227,13 @@ std::tuple<std::add_pointer_t<std::add_const_t<Ts>>...> assets::detail::generic_
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
std::array<typename assets::detail::generic_mesh_store<Ts...>::count_type, 1 + sizeof...(Ts)>
|
||||
assets::detail::generic_mesh_store<Ts...>::array_counts() const
|
||||
std::array<typename assets::detail::generic_mesh_store<z3d::structure<Ts...>>::count_type, 1 + sizeof...(Ts)>
|
||||
assets::detail::generic_mesh_store<z3d::structure<Ts...>>::array_counts() const
|
||||
{
|
||||
return [&]<auto... Is>(std::index_sequence<Is>)
|
||||
{
|
||||
return std::array{
|
||||
m_indices.size(),
|
||||
m_triangles.size(),
|
||||
std::get<Is>(m_component_arrays).size()...
|
||||
};
|
||||
}
|
||||
@@ -239,129 +241,191 @@ assets::detail::generic_mesh_store<Ts...>::array_counts() const
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_mesh_store<Ts...>::id_type assets::detail::generic_mesh_store<Ts...>::add(
|
||||
const mesh_data& mesh
|
||||
) {
|
||||
bool assets::detail::generic_mesh_store<z3d::structure<Ts...>>::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<typename... Ts>
|
||||
bool assets::detail::generic_mesh_store<z3d::structure<Ts...>>::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<typename... Ts>
|
||||
std::pair<typename assets::detail::generic_mesh_store<z3d::structure<Ts...>>::iterator, bool> assets::detail::generic_mesh_store<z3d::structure<Ts...>>::find(id_type id)
|
||||
{
|
||||
auto lock = std::shared_lock{ m_mutex };
|
||||
|
||||
return unsafe_find(id);
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
std::pair<typename assets::detail::generic_mesh_store<z3d::structure<Ts...>>::const_iterator, bool> assets::detail::generic_mesh_store<z3d::structure<Ts...>>::find(id_type id) const
|
||||
{
|
||||
auto lock = std::shared_lock{ m_mutex };
|
||||
|
||||
return unsafe_find(id);
|
||||
}
|
||||
|
||||
|
||||
template<typename... Ts>
|
||||
bool assets::detail::generic_mesh_store<z3d::structure<Ts...>>::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<count_type>::max()
|
||||
);
|
||||
|
||||
// finding out correct component flags and count
|
||||
[&]<auto... Is>(std::integer_sequence<Is...>)
|
||||
{
|
||||
const auto& component_array = std::get<Is>(vertices);
|
||||
const auto& component_array = std::get<Is>(data.component_arrays);
|
||||
if (not component_array.empty())
|
||||
{
|
||||
// TODO check count
|
||||
const auto component_count = static_cast<count_type>(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<Ts...>{});
|
||||
|
||||
// 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<component_flag_type, count_type, count_type>{
|
||||
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
|
||||
[&]<auto... Is>(std::integer_sequence<Is...>)
|
||||
{
|
||||
const auto& src_array = std::get<Is>(vertices);
|
||||
auto& dst_array = std::get<Is>(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<bool>(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<Is>(data.component_arrays);
|
||||
auto& dst_component_array = std::get<Is>(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<Ts...>{});
|
||||
|
||||
// Insert material
|
||||
m_material_ids.emplace_back(mesh.material_id());
|
||||
|
||||
// TODO check count
|
||||
m_component_flag_counts.emplace_back(
|
||||
mesh.component_flags,
|
||||
static_cast<count_type>(indices.size()),
|
||||
min_component_count
|
||||
);
|
||||
|
||||
return id;
|
||||
return new_entry;
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
std::pair<typename assets::detail::generic_mesh_store<Ts...>::iterator_type, bool> assets::detail::generic_mesh_store<Ts...>::find(id_type id)
|
||||
std::pair<typename assets::detail::generic_mesh_store<z3d::structure<Ts...>>::iterator, bool> assets::detail::generic_mesh_store<z3d::structure<Ts...>>::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<typename... Ts>
|
||||
std::pair<typename assets::detail::generic_mesh_store<Ts...>::const_iterator, bool> assets::detail::generic_mesh_store<Ts...>::find(id_type id) const
|
||||
std::pair<typename assets::detail::generic_mesh_store<z3d::structure<Ts...>>::const_iterator, bool> assets::detail::generic_mesh_store<z3d::structure<Ts...>>::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<typename... Ts>
|
||||
void assets::detail::generic_mesh_store<Ts...>::remove(const iterator_type& it)
|
||||
void assets::detail::generic_mesh_store<z3d::structure<Ts...>>::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);
|
||||
|
||||
[&]<auto... Is>(std::index_sequence<Is>)
|
||||
{
|
||||
([&]{
|
||||
auto& component_vector = std::get<Is>(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<Is>(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<Ts...>{});
|
||||
|
||||
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<typename... Ts>
|
||||
void assets::detail::generic_mesh_store<Ts...>::clear()
|
||||
void assets::detail::generic_mesh_store<z3d::structure<Ts...>>::clear()
|
||||
{
|
||||
auto lock = std::unique_lock{ m_mutex };
|
||||
|
||||
m_ids.clear();
|
||||
m_indices.clear();
|
||||
m_triangles.clear();
|
||||
[&]<auto... Is>(std::index_sequence<Is>)
|
||||
{
|
||||
std::get<Is>(m_component_arrays).clear();
|
||||
@@ -371,11 +435,21 @@ void assets::detail::generic_mesh_store<Ts...>::clear()
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_mesh_store<Ts...>::iterator_type assets::detail::generic_mesh_store<Ts...>::begin()
|
||||
std::shared_lock<std::shared_mutex> assets::detail::generic_mesh_store<z3d::structure<Ts...>>::acquire_read_lock() const {
|
||||
return std::shared_lock{ m_mutex };
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
std::unique_lock<std::shared_mutex> assets::detail::generic_mesh_store<z3d::structure<Ts...>>::acquire_write_lock() {
|
||||
return std::unique_lock{ m_mutex };
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_mesh_store<z3d::structure<Ts...>>::iterator assets::detail::generic_mesh_store<z3d::structure<Ts...>>::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<Ts...>::iterator_type assets::detail
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_mesh_store<Ts...>::iterator_type assets::detail::generic_mesh_store<Ts...>::end()
|
||||
typename assets::detail::generic_mesh_store<z3d::structure<Ts...>>::iterator assets::detail::generic_mesh_store<z3d::structure<Ts...>>::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... Ts>
|
||||
typename assets::detail::generic_mesh_store<Ts...>::const_iterator assets::detail::generic_mesh_store<Ts...>::begin() const
|
||||
typename assets::detail::generic_mesh_store<z3d::structure<Ts...>>::const_iterator assets::detail::generic_mesh_store<z3d::structure<Ts...>>::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<Ts...>::const_iterator assets::detai
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_mesh_store<Ts...>::const_iterator assets::detail::generic_mesh_store<Ts...>::end() const
|
||||
typename assets::detail::generic_mesh_store<z3d::structure<Ts...>>::const_iterator assets::detail::generic_mesh_store<z3d::structure<Ts...>>::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<Ts...>::const_iterator assets::detai
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_mesh_store<Ts...>::const_iterator assets::detail::generic_mesh_store<Ts...>::cbegin() const
|
||||
typename assets::detail::generic_mesh_store<z3d::structure<Ts...>>::const_iterator assets::detail::generic_mesh_store<z3d::structure<Ts...>>::cbegin() const
|
||||
{
|
||||
return const_cast<const generic_mesh_store*>(this)->begin();
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_mesh_store<Ts...>::const_iterator assets::detail::generic_mesh_store<Ts...>::cend() const
|
||||
typename assets::detail::generic_mesh_store<z3d::structure<Ts...>>::const_iterator assets::detail::generic_mesh_store<z3d::structure<Ts...>>::cend() const
|
||||
{
|
||||
return const_cast<const generic_mesh_store*>(this)->end();
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_mesh_store<Ts...>::view_type assets::detail::generic_mesh_store<Ts...>::view()
|
||||
{
|
||||
return { begin(), end() };
|
||||
}
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_mesh_store<Ts...>::const_view_type assets::detail::generic_mesh_store<Ts...>::view() const
|
||||
{
|
||||
return { begin(), end() };
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ template<typename... Ts>
|
||||
assets::detail::generic_point_cloud_store_iterator<Ts...>::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<Ts...>::dereference(std::inde
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
std::tuple<std::add_pointer_t<Ts>...> assets::detail::generic_point_cloud_store<Ts...>::component_iterators()
|
||||
std::tuple<std::add_pointer_t<Ts>...> assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::component_iterators()
|
||||
{
|
||||
return [&]<auto... Is>(std::index_sequence<Is>)
|
||||
{
|
||||
@@ -206,7 +206,7 @@ std::tuple<std::add_pointer_t<Ts>...> assets::detail::generic_point_cloud_store<
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
std::tuple<std::add_pointer_t<std::add_const_t<Ts>>...> assets::detail::generic_point_cloud_store<Ts...>::component_iterators() const
|
||||
std::tuple<std::add_pointer_t<std::add_const_t<Ts>>...> assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::component_iterators() const
|
||||
{
|
||||
return [&]<auto... Is>(std::index_sequence<Is>)
|
||||
{
|
||||
@@ -216,8 +216,8 @@ std::tuple<std::add_pointer_t<std::add_const_t<Ts>>...> assets::detail::generic_
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
std::array<typename assets::detail::generic_point_cloud_store<Ts...>::count_type, 1 + sizeof...(Ts)>
|
||||
assets::detail::generic_point_cloud_store<Ts...>::array_counts() const
|
||||
std::array<typename assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::count_type, 1 + sizeof...(Ts)>
|
||||
assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::array_counts() const
|
||||
{
|
||||
return [&]<auto... Is>(std::index_sequence<Is>)
|
||||
{
|
||||
@@ -229,113 +229,163 @@ assets::detail::generic_point_cloud_store<Ts...>::array_counts() const
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_point_cloud_store<Ts...>::id_type assets::detail::generic_point_cloud_store<Ts...>::add(
|
||||
const id_type id,
|
||||
const data_type& point_cloud
|
||||
) {
|
||||
bool assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::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<typename... Ts>
|
||||
std::pair<typename assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::iterator, bool> assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::find(id_type id)
|
||||
{
|
||||
auto lock = std::shared_lock{ m_mutex };
|
||||
|
||||
return unsafe_find(id);
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
std::pair<typename assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::const_iterator, bool> assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::find(id_type id) const
|
||||
{
|
||||
auto lock = std::shared_lock{ m_mutex };
|
||||
|
||||
return unsafe_find(id);
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
bool assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::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<count_type>::max()
|
||||
);
|
||||
|
||||
// finding out correct component flags and count
|
||||
[&]<auto... Is>(std::integer_sequence<Is...>)
|
||||
{
|
||||
const auto& component_array = std::get<Is>(vertices);
|
||||
const auto& component_array = std::get<Is>(data.component_arrays);
|
||||
if (not component_array.empty())
|
||||
{
|
||||
// TODO check count
|
||||
const auto component_count = static_cast<count_type>(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<Ts...>{});
|
||||
|
||||
// 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<component_flag_type, count_type>{
|
||||
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;
|
||||
}
|
||||
|
||||
[&]<auto... Is>(std::integer_sequence<Is...>)
|
||||
{
|
||||
const auto& src_array = std::get<Is>(vertices);
|
||||
auto& dst_array = std::get<Is>(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<bool>(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<Is>(data.component_arrays);
|
||||
auto& dst_component_array = std::get<Is>(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<Ts...>{});
|
||||
|
||||
// TODO check count
|
||||
m_component_flag_counts.emplace_back(
|
||||
point_cloud.component_flags,
|
||||
min_component_count
|
||||
);
|
||||
|
||||
return id;
|
||||
return new_entry;
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
std::pair<typename assets::detail::generic_point_cloud_store<Ts...>::iterator_type, bool> assets::detail::generic_point_cloud_store<Ts...>::find(id_type id)
|
||||
std::pair<typename assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::iterator, bool> assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::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<typename... Ts>
|
||||
std::pair<typename assets::detail::generic_point_cloud_store<Ts...>::const_iterator, bool> assets::detail::generic_point_cloud_store<Ts...>::find(id_type id) const
|
||||
std::pair<typename assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::const_iterator, bool> assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::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<typename... Ts>
|
||||
void assets::detail::generic_point_cloud_store<Ts...>::remove(const iterator_type& it)
|
||||
void assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::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);
|
||||
|
||||
[&]<auto... Is>(std::index_sequence<Is>)
|
||||
{
|
||||
([&]{
|
||||
auto& component_vector = std::get<Is>(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<Is>(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<Ts...>{});
|
||||
|
||||
m_component_flag_counts.erase(m_component_flag_counts.begin() + it.m_index);
|
||||
m_ids.erase(m_ids.begin() + it.m_index);
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
void assets::detail::generic_point_cloud_store<Ts...>::clear()
|
||||
void assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::clear()
|
||||
{
|
||||
auto lock = std::unique_lock{ m_mutex };
|
||||
|
||||
m_ids.clear();
|
||||
[&]<auto... Is>(std::index_sequence<Is>)
|
||||
{
|
||||
@@ -345,9 +395,19 @@ void assets::detail::generic_point_cloud_store<Ts...>::clear()
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_point_cloud_store<Ts...>::iterator_type assets::detail::generic_point_cloud_store<Ts...>::begin()
|
||||
std::shared_lock<std::shared_mutex> assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::acquire_read_lock() const {
|
||||
return std::shared_lock{ m_mutex };
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
std::unique_lock<std::shared_mutex> assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::acquire_write_lock() {
|
||||
return std::unique_lock{ m_mutex };
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::iterator assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::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<Ts...>::iterator_type assets:
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_point_cloud_store<Ts...>::iterator_type assets::detail::generic_point_cloud_store<Ts...>::end()
|
||||
typename assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::iterator assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::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<Ts...>::iterator_type assets:
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_point_cloud_store<Ts...>::const_iterator assets::detail::generic_point_cloud_store<Ts...>::begin() const
|
||||
typename assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::const_iterator assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::begin() const
|
||||
{
|
||||
return const_iterator{
|
||||
m_ids.data(),
|
||||
@@ -381,7 +441,7 @@ typename assets::detail::generic_point_cloud_store<Ts...>::const_iterator assets
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_point_cloud_store<Ts...>::const_iterator assets::detail::generic_point_cloud_store<Ts...>::end() const
|
||||
typename assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::const_iterator assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::end() const
|
||||
{
|
||||
return const_iterator{
|
||||
m_ids.data(),
|
||||
@@ -393,13 +453,13 @@ typename assets::detail::generic_point_cloud_store<Ts...>::const_iterator assets
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_point_cloud_store<Ts...>::const_iterator assets::detail::generic_point_cloud_store<Ts...>::cbegin() const
|
||||
typename assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::const_iterator assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::cbegin() const
|
||||
{
|
||||
return const_cast<const generic_point_cloud_store*>(this)->begin();
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
typename assets::detail::generic_point_cloud_store<Ts...>::const_iterator assets::detail::generic_point_cloud_store<Ts...>::cend() const
|
||||
typename assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::const_iterator assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::cend() const
|
||||
{
|
||||
return const_cast<const generic_point_cloud_store*>(this)->end();
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ assets::pose_list_store_iterator<Char>::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<Char>::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::iterator_type, bool> assets::pose_list_store::find(id_type id)
|
||||
inline std::pair<assets::pose_list_store::iterator, bool> 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::const_iterator, bool> 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::const_iterator, bool> assets::pose_list_store::find(id_type id) const
|
||||
|
||||
inline std::pair<assets::pose_list_store::iterator, bool> 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::const_iterator, bool> 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<std::shared_mutex> assets::pose_list_store::acquire_read_lock() const {
|
||||
return std::shared_lock{ m_mutex };
|
||||
}
|
||||
|
||||
std::unique_lock<std::shared_mutex> 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(),
|
||||
|
||||
@@ -17,7 +17,7 @@ assets::shader_source_store_iterator<Char>::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<Char>::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::iterator_type, bool> 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<typename... Ts>
|
||||
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::const_iterator, bool> assets::shader_source_store::find(id_type id) const
|
||||
inline std::pair<assets::shader_source_store::iterator, bool> 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::const_iterator, bool> 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<std::shared_mutex> assets::shader_source_store::acquire_read_lock() const {
|
||||
return std::shared_lock{ m_mutex };
|
||||
}
|
||||
|
||||
std::unique_lock<std::shared_mutex> 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(),
|
||||
|
||||
@@ -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<const std::string_view> values,
|
||||
model_geometry::types& geometry_type
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "assets/file_parsers/mtl_loader.hpp"
|
||||
#include "assets/file_parsers/mtl_parser.hpp"
|
||||
|
||||
#include <charconv>
|
||||
#include <fstream>
|
||||
@@ -7,20 +7,20 @@
|
||||
#include "util/logger.hpp"
|
||||
#include "util/for_each.hpp"
|
||||
#include "util/line_parser.hpp"
|
||||
#include <execution>
|
||||
|
||||
#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<codes>(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<int>(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<char>(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<int>(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<codes>(
|
||||
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::texture_id> 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<typename T, std::size_t Count>
|
||||
std::errc parse_numeric_vector(std::string_view param, std::array<T, Count>& 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<T, Count>& val
|
||||
};
|
||||
|
||||
|
||||
void mtl_loader::find_textures(
|
||||
|
||||
|
||||
void assets::mtl_parser::find_textures(
|
||||
std::span<char> 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<char>(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<codes>(
|
||||
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<float, 1> 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<float, 1> 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 {};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user