From 27977c1738a0b8a9f352dd5942aac3c6fc5b2cf9 Mon Sep 17 00:00:00 2001 From: zy4n Date: Tue, 1 Apr 2025 21:51:56 +0200 Subject: [PATCH] Ported the obj parser. --- CMakeLists.txt | 441 +++++++------ .../assets/components/material_components.hpp | 2 +- .../components/mesh_vertex_components.hpp | 2 + .../data/generic/component_array_set.hpp | 4 + include/assets/data/generic/component_set.hpp | 2 +- .../generic/generic_basic_store.hpp | 2 +- .../generic/generic_material_store.hpp | 11 +- .../generic/generic_mesh_store.hpp | 4 +- .../assets/data_stores/pose_list_store.hpp | 10 +- .../data_stores/shader_source_store.hpp | 1 - .../generic/generic_3dtk_loader.hpp | 61 +- include/assets/file_parsers/mtl_parser.hpp | 45 +- .../{obj_loader.hpp => obj_parser.hpp} | 69 +- include/assets/file_parsers/stl_loader.hpp | 65 +- include/util/array_hash.hpp | 18 + include/util/enum_bitfield_operators.hpp | 13 +- include/util/file_id_lookup.hpp | 2 +- include/util/id_type.hpp | 12 +- include/util/vector_hash.hpp | 24 + main.cpp | 62 +- source/assets/data/material_data.ipp | 2 +- source/assets/data/mesh_data.ipp | 6 +- source/assets/data/point_cloud_data.ipp | 16 +- .../generic/generic_basic_store.ipp | 8 +- .../generic/generic_material_store.ipp | 85 +-- .../generic/generic_mesh_store.ipp | 84 +-- .../generic/generic_point_cloud_store.ipp | 70 +- source/assets/data_stores/pose_list_store.ipp | 8 +- .../data_stores/shader_source_store.ipp | 43 +- .../generic/generic_3dtk_loader.ipp | 168 ++++- source/assets/file_parsers/mtl_parser.cpp | 460 ++++++------- source/assets/file_parsers/obj_loader.cpp | 602 ------------------ source/assets/file_parsers/obj_parser.cpp | 530 +++++++++++++++ source/assets/file_parsers/stl_loader.cpp | 298 ++++----- 34 files changed, 1676 insertions(+), 1554 deletions(-) rename include/assets/file_parsers/{obj_loader.hpp => obj_parser.hpp} (50%) create mode 100644 include/util/array_hash.hpp create mode 100644 include/util/vector_hash.hpp delete mode 100755 source/assets/file_parsers/obj_loader.cpp create mode 100755 source/assets/file_parsers/obj_parser.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 17add23..7099f5c 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,243 +9,237 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fmacro-prefix-map=${CMAKE_CURRENT_SOURC add_executable(z3d main.cpp include/assets/components/material_components.hpp + include/assets/components/mesh_shader_components.hpp + include/assets/components/mesh_vertex_components.hpp + include/assets/components/mesh_vertex_components.hpp include/assets/components/point_cloud_vertex_components.hpp - include/assets/components/mesh_vertex_components.hpp - include/assets/data/material_data.hpp - include/assets/data/mesh_data.hpp - include/assets/data/point_cloud_data.hpp - include/assets/file_parsers/kitti_parser.hpp - include/assets/file_parsers/obj_loader.hpp - include/assets/file_parsers/stl_loader.hpp - include/assets/file_parsers/uos_loader.hpp - include/assets/components/mesh_vertex_components.hpp - include/scene/camera.hpp - include/scene/flying_camera.hpp - include/opengl/handles/mesh_handle.hpp - include/opengl/handles/point_cloud_handle.hpp - include/opengl/handles/shader_program_handle.hpp - include/opengl/handles/texture_handle.hpp - include/opengl/data/mesh_data.hpp - include/opengl/data/point_cloud_data.hpp - include/opengl/data/shader_program_data.hpp - include/scene/lighting_setup.hpp - include/rendering/batch_renderers/mesh_batch_renderer.hpp - include/opengl/error.hpp - include/rendering/batches/mesh_batch.hpp - include/rendering/batches/point_cloud_batch.hpp - include/util/arx.hpp - include/util/extra_arx_parsers.hpp - include/util/for_each.hpp - include/util/function.hpp - include/util/image.hpp - include/util/logger.hpp - include/util/string_indexer.hpp - include/util/string_literal.hpp - include/util/uix.hpp - source/assets/file_parsers/stl_loader.cpp - source/assets/file_parsers/obj_loader.cpp - source/scene/flying_camera.cpp - source/opengl/data/point_cloud_data.cpp - source/opengl/handles/shader_program_handle.ipp - source/opengl/data/texture_data.ipp - source/opengl/data/mesh_data.cpp - include/opengl/error.hpp - source/opengl/data/shader_program_data.cpp - source/opengl/handles/mesh_handle.ipp - source/opengl/handles/point_cloud_handle.ipp - source/opengl/handles/texture_handle.ipp - include/assets/data/uniform_surface_properties.hpp - include/util/unroll_bool_template.hpp - include/rendering/batch_renderers/point_cloud_batch_renderer.hpp - source/rendering/batches/mesh_batch.ipp - source/rendering/batches/point_cloud_batch.ipp - include/opengl/shading/uniform.hpp - include/opengl/type_utils.hpp - include/util/binary_ifstream.hpp - source/assets/file_parsers/kitti_parser.cpp - include/assets/file_parsers/generic/generic_3dtk_loader.hpp - include/assets/file_parsers/uosr_loader.hpp - include/assets/file_parsers/uos_normal_loader.hpp - include/assets/file_parsers/uos_rgb_loader.hpp - include/assets/data_loaders/mesh_loader.hpp - source/assets/data_loaders/mesh_loader.cpp - source/assets/data_loaders/mesh_loader.cpp - include/assets/data_loaders/point_cloud_loader.hpp - include/assets/data_loaders/generic/base_dynamic_loader.hpp - source/assets/data_loaders/generic/base_dynamic_loader.ipp - source/assets/data_loaders/point_cloud_loader.cpp - include/opengl/handles/matrix_handles.hpp - include/viewer/instance.hpp - include/opengl/data/material_data.hpp - include/opengl/handles/material_handle.hpp - include/opengl/handles/surface_properties_handle.hpp - include/opengl/handles/alpha_handle.hpp - source/opengl/data/material_data.ipp - include/util/specialised_lambda.hpp - include/viewer/asset_types.hpp - source/viewer/instance.cpp - include/viewer/asset_loader.hpp - source/viewer/asset_loader.cpp - include/assets/file_parsers/glsl_parser.hpp - include/assets/data/shader_source_data.hpp - source/assets/file_parsers/glsl_parser.cpp - include/viewer/settings.hpp - include/opengl/data/shader_data.hpp - source/opengl/data/shader_data.ipp - source/opengl/data/point_cloud_data.ipp - source/opengl/data/shader_data.cpp - include/opengl/handles/shader_handle.hpp - include/util/string_lookup.hpp - include/viewer/dynamic_shader_program_loading.hpp - source/viewer/dynamic_shader_program_loading.cpp - source/opengl/handles/shader_program_handle.cpp - include/opengl/shader_program_lookup.hpp - source/opengl/shader_program_lookup.cpp - include/opengl/shading/attributes/point_cloud_attributes.hpp - include/opengl/shading/uniforms/mesh_uniforms.hpp - include/opengl/shading/uniforms/point_cloud_uniforms.hpp - include/opengl/shading/features/mesh_features.hpp - include/opengl/shading/features/point_cloud_features.hpp - include/rendering/requirements/mesh_requirements.hpp - include/rendering/requirements/point_cloud_requirements.hpp - include/rendering/modes/mesh_modes.hpp - include/rendering/modes/point_cloud_modes.hpp - source/rendering/batch_renderers/mesh_batch_renderer.cpp - source/rendering/batch_renderers/point_cloud_batch_renderer.cpp - include/rendering/shader_program_lookups/mesh_lookup.hpp - include/rendering/shader_program_lookups/mesh_lookup.hpp - source/rendering/shader_program_lookups/mesh_lookup.cpp - source/rendering/shader_program_lookups/point_cloud_lookup.cpp - include/rendering/shader_program_lookups/point_cloud_lookup.hpp - include/geometry/aabb.hpp - source/geometry/normal_estimation.cpp - include/geometry/normal_estimation.hpp + include/assets/components/shader_components.hpp include/assets/components/texture_components.hpp - include/util/enum_bitfield_operators.hpp - include/assets/data/texture_data.hpp - source/assets/data/mesh_data.ipp - source/assets/data/material_data.ipp - include/assets/data/generic/component_array_set.hpp - source/assets/data/texture_data.ipp - source/assets/data/point_cloud_data.ipp - include/assets/file_parsers/mtl_parser.hpp - include/assets/data_loaders/material_loader.hpp - include/util/id_type.hpp + # include/assets/data_loaders/generic/base_dynamic_loader.hpp + # include/assets/data_loaders/material_library_loader.hpp + # include/assets/data_loaders/material_loader.hpp + # include/assets/data_loaders/mesh_loader.hpp + # include/assets/data_loaders/point_cloud_loader.hpp + # include/assets/data_loaders/texture_loader.hpp + include/assets/data_stores.hpp include/assets/data_stores/generic/generic_basic_store.hpp - source/assets/data_stores/generic/generic_basic_store.ipp + include/assets/data_stores/generic/generic_material_store.hpp + include/assets/data_stores/generic/generic_mesh_store.hpp + include/assets/data_stores/generic/generic_point_cloud_store.hpp + include/assets/data_stores/material_library_store.hpp include/assets/data_stores/material_store.hpp include/assets/data_stores/mesh_store.hpp include/assets/data_stores/point_cloud_store.hpp - include/util/result.hpp - source/assets/file_parsers/mtl_parser.cpp - include/util/line_parser.hpp - include/assets/data_loaders/texture_loader.hpp - source/assets/data_loaders/texture_loader.cpp - include/assets/data_stores/texture_store.hpp - include/opengl/data_managers/texture_manager.hpp - include/assets/prefetch_lookups/mesh_prefetch_lookup.hpp - include/assets/prefetch_lookups/point_cloud_prefetch_lookup.hpp - include/assets/prefetch_lookups/material_prefetch_lookup.hpp - include/assets/prefetch_lookups/texture_prefetch_lookup.hpp - include/assets/prefetch_lookups/pose_prefetch_lookup.hpp + include/assets/data_stores/pose_list_store.hpp include/assets/data_stores/pose_store.hpp - include/assets/file_parsers/kitti_pose_parser.hpp - include/assets/file_parsers/threedtk_pose_loader.hpp - source/assets/file_parsers/threedtk_pose_loader.cpp - include/assets/data/pose_data.hpp - source/assets/file_parsers/kitti_pose_parser.cpp - include/util/string_list.hpp - include/assets/data_stores/material_library_store.hpp - include/assets/data/material_library_data.hpp - include/assets/data_loaders/material_library_loader.hpp - include/assets/prefetch_lookups/material_library_prefetch_lookup.hpp - include/assets/prefetch_lookups/shader_prefetch_lookup.hpp include/assets/data_stores/shader_source_store.hpp - include/assets/file_parsers/generic/generic_3dtk_loader.hpp - source/assets/file_parsers/generic/generic_3dtk_loader.ipp - source/assets/prefetch_lookups/pose_prefetch_lookup.cpp - include/assets/data_stores.hpp - include/opengl/metadata/shader_source_metadata.hpp - source/opengl/data_managers/shader_manager.cpp - include/opengl/shading/model_geometry.hpp - include/opengl/shading/shader_stage.hpp - include/opengl/shading/requirements/shader_program_requirements.hpp - include/opengl/shading/attributes/mesh_attributes.hpp - include/opengl/data_managers/shader_source_manager.hpp - source/opengl/data_managers/shader_source_manager.cpp - include/opengl/shading/shader_metadata_language.hpp - include/opengl/shading/features/generic_features.hpp - include/opengl/shading/features/combined_features.hpp - include/opengl/metadata/preprocessed_shader_source_metadata.hpp - include/opengl/shading/requirements/shader_requirements.hpp - include/opengl/metadata/shader_metadata.hpp - include/opengl/metadata/shader_set_metadata.hpp - include/opengl/handles/shader_handle_set.hpp - include/opengl/data_managers/shader_program_manager.hpp - include/opengl/metadata/shader_program_metadata.hpp - source/opengl/data_managers/shader_program_manager.cpp - source/opengl/data_managers/texture_manager.cpp - include/util/reference_counter.hpp - include/opengl/resource_management/resource_manager.hpp - source/opengl/resource_management/resource_manager.ipp - include/opengl/data_managers/shader_manager.hpp - include/opengl/data_managers/mesh_vertex_buffer_manager.hpp - source/opengl/data_managers/mesh_vertex_buffer_manager.cpp - include/opengl/resource_management/reference_counter.hpp - include/opengl/resource_management/reference_counter.hpp - include/opengl/resource_management/resource_handle.hpp - source/opengl/resource_management/resource_handle.ipp - include/opengl/handles/vertex_buffer_handle.hpp - source/opengl/handles/vertex_buffer_handle.ipp - include/opengl/handles/index_buffer_handle.hpp - source/opengl/handles/index_buffer_handle.ipp - include/opengl/metadata/texture_metadata.hpp - include/opengl/data_managers/mesh_index_buffer_manager.hpp - include/opengl/metadata/index_buffer_metadata.hpp - source/opengl/data_managers/mesh_index_buffer_manager.cpp - include/opengl/data_managers/point_cloud_vertex_buffer_manager.hpp - source/opengl/data_managers/point_cloud_vertex_buffer_manager.cpp - include/assets/data_views/mesh_view.hpp - include/assets/data_views/point_cloud_view.hpp - include/assets/data_views/shader_source_view.hpp - include/assets/data_stores/generic/generic_mesh_store.hpp - source/assets/data_stores/generic/generic_mesh_store.ipp - include/assets/data_stores/generic/generic_point_cloud_store.hpp - source/assets/data_stores/generic/generic_point_cloud_store.ipp - include/assets/data_views/material_view.hpp - include/assets/data_views/texture_view.hpp - include/assets/data_stores/generic/generic_material_store.hpp - source/assets/data_stores/generic/generic_material_store.ipp - source/assets/data_stores/shader_source_store.ipp - include/opengl/metadata/mesh_vertex_buffer_metadata.hpp - include/opengl/metadata/point_cloud_vertex_buffer_metadata.hpp - include/opengl/data_managers/material_manager.hpp - include/opengl/metadata/uniform_buffer_alignment_metadata.hpp - include/opengl/types.hpp - include/opengl/metadata/material_metadata.hpp - include/opengl/shading/sampler_uniforms/mesh_samplers_uniforms.hpp - include/opengl/shading/sampler_uniform.hpp - include/opengl/shading/uniform_block.hpp - include/opengl/shading/uniform_blocks/mesh_uniform_blocks.hpp - include/opengl/shading/uniform_blocks/point_cloud_uniform_blocks.hpp - include/config/primitives.hpp - include/assets/data/generic/component_set.hpp + include/assets/data_stores/texture_store.hpp include/assets/data_views/generic/generic_mesh_view.hpp include/assets/data_views/generic/generic_point_cloud_view.hpp - include/assets/identifiers.hpp - include/assets/fallback_data/fallback_texture.hpp - source/assets/fallback_data/default_texture_data.cpp + include/assets/data_views/material_view.hpp + include/assets/data_views/mesh_view.hpp + include/assets/data_views/point_cloud_view.hpp + include/assets/data_views/pose_list_view.hpp + include/assets/data_views/shader_source_view.hpp + include/assets/data_views/texture_view.hpp + include/assets/data/generic/component_array_set.hpp + include/assets/data/generic/component_set.hpp + include/assets/data/material_data.hpp + include/assets/data/material_library_data.hpp + include/assets/data/mesh_data.hpp + include/assets/data/point_cloud_data.hpp + include/assets/data/pose_data.hpp + include/assets/data/pose_list_data.hpp + include/assets/data/shader_source_data.hpp + include/assets/data/texture_data.hpp + include/assets/data/uniform_surface_properties.hpp include/assets/fallback_data/fallback_material.hpp - source/assets/fallback_data/fallback_material.cpp - include/assets/components/mesh_shader_components.hpp - include/assets/components/shader_components.hpp + include/assets/fallback_data/fallback_texture.hpp + include/assets/file_parsers/generic/generic_3dtk_loader.hpp + include/assets/file_parsers/generic/generic_3dtk_loader.hpp + include/assets/file_parsers/glsl_parser.hpp + include/assets/file_parsers/kitti_parser.hpp + include/assets/file_parsers/kitti_pose_parser.hpp + include/assets/file_parsers/mtl_parser.hpp + include/assets/file_parsers/obj_parser.hpp + include/assets/file_parsers/stl_loader.hpp + include/assets/file_parsers/threedtk_pose_loader.hpp + include/assets/file_parsers/uos_loader.hpp + include/assets/file_parsers/uos_normal_loader.hpp + include/assets/file_parsers/uos_rgb_loader.hpp + include/assets/file_parsers/uosr_loader.hpp + include/assets/identifiers.hpp include/assets/model_geometry.hpp include/assets/path_id_lookups.hpp + include/config/primitives.hpp + # include/geometry/aabb.hpp + # include/geometry/normal_estimation.hpp + # include/opengl/data_managers/material_manager.hpp + # include/opengl/data_managers/mesh_index_buffer_manager.hpp + # include/opengl/data_managers/mesh_vertex_buffer_manager.hpp + # include/opengl/data_managers/point_cloud_vertex_buffer_manager.hpp + # include/opengl/data_managers/shader_manager.hpp + # include/opengl/data_managers/shader_program_manager.hpp + # include/opengl/data_managers/shader_source_manager.hpp + # include/opengl/data_managers/texture_manager.hpp + # include/opengl/data/material_data.hpp + # include/opengl/data/mesh_data.hpp + # include/opengl/data/point_cloud_data.hpp + # include/opengl/data/shader_data.hpp + # include/opengl/data/shader_program_data.hpp + # include/opengl/error.hpp + # include/opengl/error.hpp + # include/opengl/handles/alpha_handle.hpp + # include/opengl/handles/index_buffer_handle.hpp + # include/opengl/handles/material_handle.hpp + # include/opengl/handles/matrix_handles.hpp + # include/opengl/handles/mesh_handle.hpp + # include/opengl/handles/point_cloud_handle.hpp + # include/opengl/handles/shader_handle_set.hpp + # include/opengl/handles/shader_handle.hpp + # include/opengl/handles/shader_program_handle.hpp + # include/opengl/handles/surface_properties_handle.hpp + # include/opengl/handles/texture_handle.hpp + # include/opengl/handles/vertex_buffer_handle.hpp + # include/opengl/metadata/index_buffer_metadata.hpp + # include/opengl/metadata/material_metadata.hpp + # include/opengl/metadata/mesh_vertex_buffer_metadata.hpp + # include/opengl/metadata/point_cloud_vertex_buffer_metadata.hpp + # include/opengl/metadata/preprocessed_shader_source_metadata.hpp + # include/opengl/metadata/shader_metadata.hpp + # include/opengl/metadata/shader_program_metadata.hpp + # include/opengl/metadata/shader_set_metadata.hpp + # include/opengl/metadata/shader_source_metadata.hpp + # include/opengl/metadata/texture_metadata.hpp + # include/opengl/metadata/uniform_buffer_alignment_metadata.hpp + # include/opengl/resource_management/reference_counter.hpp + # include/opengl/resource_management/reference_counter.hpp + # include/opengl/resource_management/resource_handle.hpp + # include/opengl/resource_management/resource_manager.hpp + # include/opengl/shader_program_lookup.hpp + # include/opengl/shading/attributes/mesh_attributes.hpp + # include/opengl/shading/attributes/point_cloud_attributes.hpp + # include/opengl/shading/features/combined_features.hpp + # include/opengl/shading/features/generic_features.hpp + # include/opengl/shading/features/mesh_features.hpp + # include/opengl/shading/features/point_cloud_features.hpp + # include/opengl/shading/model_geometry.hpp + # include/opengl/shading/requirements/shader_program_requirements.hpp + # include/opengl/shading/requirements/shader_requirements.hpp + # include/opengl/shading/sampler_uniform.hpp + # include/opengl/shading/sampler_uniforms/mesh_samplers_uniforms.hpp + # include/opengl/shading/shader_metadata_language.hpp + # include/opengl/shading/shader_stage.hpp + # include/opengl/shading/uniform_block.hpp + # include/opengl/shading/uniform_blocks/mesh_uniform_blocks.hpp + # include/opengl/shading/uniform_blocks/point_cloud_uniform_blocks.hpp + # include/opengl/shading/uniform.hpp + # include/opengl/shading/uniforms/mesh_uniforms.hpp + # include/opengl/shading/uniforms/point_cloud_uniforms.hpp + # include/opengl/type_utils.hpp + # include/opengl/types.hpp + # include/rendering/batch_renderers/mesh_batch_renderer.hpp + # include/rendering/batch_renderers/point_cloud_batch_renderer.hpp + # include/rendering/batches/mesh_batch.hpp + # include/rendering/batches/point_cloud_batch.hpp + # include/rendering/modes/mesh_modes.hpp + # include/rendering/modes/point_cloud_modes.hpp + # include/rendering/requirements/mesh_requirements.hpp + # include/rendering/requirements/point_cloud_requirements.hpp + # include/rendering/shader_program_lookups/mesh_lookup.hpp + # include/rendering/shader_program_lookups/mesh_lookup.hpp + # include/rendering/shader_program_lookups/point_cloud_lookup.hpp + # include/scene/camera.hpp + # include/scene/flying_camera.hpp + # include/scene/lighting_setup.hpp + include/util/arx.hpp + include/util/binary_ifstream.hpp + include/util/enum_bitfield_operators.hpp + include/util/extra_arx_parsers.hpp include/util/file_id_lookup.hpp - include/assets/data/pose_list_data.hpp - include/assets/data_stores/pose_list_store.hpp - include/assets/data_views/pose_list_view.hpp + include/util/for_each.hpp + include/util/function.hpp + include/util/id_type.hpp + include/util/image.hpp + include/util/line_parser.hpp + include/util/logger.hpp + include/util/reference_counter.hpp + include/util/result.hpp + include/util/specialised_lambda.hpp + include/util/string_indexer.hpp + include/util/string_list.hpp + include/util/string_literal.hpp + include/util/string_lookup.hpp + include/util/uix.hpp + include/util/unroll_bool_template.hpp include/util/vector_replace_range.hpp + # include/viewer/asset_loader.hpp + # include/viewer/asset_types.hpp + # include/viewer/dynamic_shader_program_loading.hpp + # include/viewer/instance.hpp + # include/viewer/settings.hpp + # source/assets/data_loaders/generic/base_dynamic_loader.ipp + # source/assets/data_loaders/mesh_loader.cpp + # source/assets/data_loaders/mesh_loader.cpp + # source/assets/data_loaders/point_cloud_loader.cpp + # source/assets/data_loaders/texture_loader.cpp + source/assets/data_stores/generic/generic_basic_store.ipp + source/assets/data_stores/generic/generic_material_store.ipp + source/assets/data_stores/generic/generic_mesh_store.ipp + source/assets/data_stores/generic/generic_point_cloud_store.ipp + source/assets/data_stores/shader_source_store.ipp + source/assets/data/material_data.ipp + source/assets/data/mesh_data.ipp + source/assets/data/point_cloud_data.ipp + source/assets/data/texture_data.ipp + # source/assets/fallback_data/default_texture_data.cpp + # source/assets/fallback_data/fallback_material.cpp + # source/assets/file_parsers/generic/generic_3dtk_loader.ipp + # source/assets/file_parsers/glsl_parser.cpp + # source/assets/file_parsers/kitti_parser.cpp + # source/assets/file_parsers/kitti_pose_parser.cpp + source/assets/file_parsers/mtl_parser.cpp + source/assets/file_parsers/obj_parser.cpp + include/util/array_hash.hpp + include/util/vector_hash.hpp + # source/assets/file_parsers/stl_loader.cpp + # source/assets/file_parsers/threedtk_pose_loader.cpp + # source/geometry/normal_estimation.cpp + # source/opengl/data_managers/mesh_index_buffer_manager.cpp + # source/opengl/data_managers/mesh_vertex_buffer_manager.cpp + # source/opengl/data_managers/point_cloud_vertex_buffer_manager.cpp + # source/opengl/data_managers/shader_manager.cpp + # source/opengl/data_managers/shader_program_manager.cpp + # source/opengl/data_managers/shader_source_manager.cpp + # source/opengl/data_managers/texture_manager.cpp + # source/opengl/data/material_data.ipp + # source/opengl/data/mesh_data.cpp + # source/opengl/data/point_cloud_data.cpp + # source/opengl/data/point_cloud_data.ipp + # source/opengl/data/shader_data.cpp + # source/opengl/data/shader_data.ipp + # source/opengl/data/shader_program_data.cpp + # source/opengl/data/texture_data.ipp + # source/opengl/handles/index_buffer_handle.ipp + # source/opengl/handles/mesh_handle.ipp + # source/opengl/handles/point_cloud_handle.ipp + # source/opengl/handles/shader_program_handle.cpp + # source/opengl/handles/shader_program_handle.ipp + # source/opengl/handles/texture_handle.ipp + # source/opengl/handles/vertex_buffer_handle.ipp + # source/opengl/resource_management/resource_handle.ipp + # source/opengl/resource_management/resource_manager.ipp + # source/opengl/shader_program_lookup.cpp + # source/rendering/batch_renderers/mesh_batch_renderer.cpp + # source/rendering/batch_renderers/point_cloud_batch_renderer.cpp + # source/rendering/batches/mesh_batch.ipp + # source/rendering/batches/point_cloud_batch.ipp + # source/rendering/shader_program_lookups/mesh_lookup.cpp + # source/rendering/shader_program_lookups/point_cloud_lookup.cpp + # source/scene/flying_camera.cpp + # source/viewer/asset_loader.cpp + # source/viewer/dynamic_shader_program_loading.cpp + # source/viewer/instance.cpp ) target_include_directories(z3d PRIVATE include) @@ -257,7 +251,8 @@ find_package(GLEW REQUIRED) find_package(OpenGL REQUIRED) find_package(SFML REQUIRED COMPONENTS graphics system) find_package(Eigen3 3.4 REQUIRED NO_MODULE) +find_package(TBB REQUIRED NO_MODULE) include_directories(${SFML_INCLUDE_DIR}) include_directories(SYSTEM ${eigen_INCLUDE_DIR}) -target_link_libraries(z3d Eigen3::Eigen sfml-graphics sfml-system sfml-window ${OPENGL_LIBRARIES} ${GLEW_LIBRARIES}) +target_link_libraries(z3d Eigen3::Eigen sfml-graphics sfml-system sfml-window TBB::tbb ${OPENGL_LIBRARIES} ${GLEW_LIBRARIES}) diff --git a/include/assets/components/material_components.hpp b/include/assets/components/material_components.hpp index 40df84c..2cfa937 100644 --- a/include/assets/components/material_components.hpp +++ b/include/assets/components/material_components.hpp @@ -41,7 +41,7 @@ enum : z3d::size }; } -enum class flags : z3d::u8 +enum class flags : z3d::u16 { none = 0, ambient_filter = 1 << indices::ambient_filter, diff --git a/include/assets/components/mesh_vertex_components.hpp b/include/assets/components/mesh_vertex_components.hpp index 14b5e84..2367d86 100755 --- a/include/assets/components/mesh_vertex_components.hpp +++ b/include/assets/components/mesh_vertex_components.hpp @@ -45,6 +45,8 @@ enum class flags : z3d::u8 using all = z3d::structure< position, normal, + tangent, + bi_tangent, tex_coord, color, reflectance diff --git a/include/assets/data/generic/component_array_set.hpp b/include/assets/data/generic/component_array_set.hpp index a486c50..549ee1c 100644 --- a/include/assets/data/generic/component_array_set.hpp +++ b/include/assets/data/generic/component_array_set.hpp @@ -17,6 +17,10 @@ public: C component_flags; z3d::structure...> component_arrays{}; + void add() { + + } + protected: void clear_component_arrays() { diff --git a/include/assets/data/generic/component_set.hpp b/include/assets/data/generic/component_set.hpp index 79082ce..323ab3b 100644 --- a/include/assets/data/generic/component_set.hpp +++ b/include/assets/data/generic/component_set.hpp @@ -15,7 +15,7 @@ public: component_set() = default; C component_flags{}; - z3d::structure> components{}; + z3d::structure...> components{}; protected: void clear_components() diff --git a/include/assets/data_stores/generic/generic_basic_store.hpp b/include/assets/data_stores/generic/generic_basic_store.hpp index 78bc2e4..374da3b 100644 --- a/include/assets/data_stores/generic/generic_basic_store.hpp +++ b/include/assets/data_stores/generic/generic_basic_store.hpp @@ -82,7 +82,7 @@ public: using id_type = ID; using container_type = std::vector; using iterator = generic_basic_store_iterator; - using const_iterator = generic_basic_store_iterator...>; + using const_iterator = generic_basic_store_iterator>; using size_type = std::size_t; using data_type = T; diff --git a/include/assets/data_stores/generic/generic_material_store.hpp b/include/assets/data_stores/generic/generic_material_store.hpp index af036b6..12299dd 100644 --- a/include/assets/data_stores/generic/generic_material_store.hpp +++ b/include/assets/data_stores/generic/generic_material_store.hpp @@ -17,15 +17,14 @@ class generic_material_store_iterator { public: using size_type = std::size_t; - using count_type = ztu::u32; + using count_type = z3d::u32; using component_flag_type = material_components::flags; using id_type = material_id; using value_type = std::pair; - using flag_count_type = std::tuple; using id_iterator_type = id_type*; using component_iterator_type = std::tuple...>; - using flag_count_iterator_type = const flag_count_type*; + using flag_iterator_type = const component_flag_type*; using offsets_type = std::array; using difference_type = std::ptrdiff_t; @@ -39,7 +38,7 @@ private: generic_material_store_iterator( id_iterator_type ids, const component_iterator_type& components, - flag_count_iterator_type flag_counts, + flag_iterator_type flags, std::size_t index, const offsets_type& offsets ); @@ -88,7 +87,7 @@ protected: private: id_iterator_type m_ids{}; component_iterator_type m_components{}; - flag_count_iterator_type m_flag_counts{}; + flag_iterator_type m_flags{}; size_type m_index{}; offsets_type m_offsets{}; }; @@ -99,7 +98,7 @@ class generic_material_store> { public: using size_type = std::size_t; - using count_type = ztu::u32; + using count_type = z3d::u32; using component_flag_type = material_components::flags; using data_type = material_data; diff --git a/include/assets/data_stores/generic/generic_mesh_store.hpp b/include/assets/data_stores/generic/generic_mesh_store.hpp index 257aafd..c0a3419 100644 --- a/include/assets/data_stores/generic/generic_mesh_store.hpp +++ b/include/assets/data_stores/generic/generic_mesh_store.hpp @@ -19,7 +19,7 @@ class generic_mesh_store_iterator { public: using size_type = std::size_t; - using count_type = ztu::u32; + using count_type = z3d::u32; using triangle_type = z3d::index_triangle; using material_id_type = material_store::id_type; using component_flag_type = mesh_vertex_components::flags; @@ -109,7 +109,7 @@ class generic_mesh_store> { public: using size_type = std::size_t; - using count_type = ztu::u32; + using count_type = z3d::u32; using triangle_type = z3d::index_triangle; using component_flag_type = mesh_vertex_components::flags; using material_id_type = material_id; diff --git a/include/assets/data_stores/pose_list_store.hpp b/include/assets/data_stores/pose_list_store.hpp index 0e91991..f0a7f3f 100644 --- a/include/assets/data_stores/pose_list_store.hpp +++ b/include/assets/data_stores/pose_list_store.hpp @@ -12,7 +12,7 @@ namespace assets class pose_list_store; -template +template class pose_list_store_iterator { public: @@ -22,7 +22,7 @@ public: using value_type = std::pair; using id_iterator_type = id_type const*; - using pose_iterator_type = Char*; + using pose_iterator_type = Pose*; using length_iterator_type = const length_type*; using offset_type = size_type; @@ -94,8 +94,8 @@ public: using size_type = std::size_t; using count_type = ztu::u32; - using iterator = pose_list_store_iterator; - using const_iterator = pose_list_store_iterator; + using iterator = pose_list_store_iterator; + using const_iterator = pose_list_store_iterator; using data_type = pose_list_data; using id_type = pose_list_id; @@ -136,7 +136,7 @@ protected: private: std::vector m_ids; - std::vector m_poses; + std::vector m_poses; std::vector m_lengths; mutable std::shared_mutex m_mutex; }; diff --git a/include/assets/data_stores/shader_source_store.hpp b/include/assets/data_stores/shader_source_store.hpp index 507c7ca..7f6f452 100644 --- a/include/assets/data_stores/shader_source_store.hpp +++ b/include/assets/data_stores/shader_source_store.hpp @@ -111,7 +111,6 @@ public: [[nodiscard]] std::pair find(id_type id) const; - inline void remove(const iterator& it); inline void clear(); diff --git a/include/assets/file_parsers/generic/generic_3dtk_loader.hpp b/include/assets/file_parsers/generic/generic_3dtk_loader.hpp index feccde4..835bdbd 100644 --- a/include/assets/file_parsers/generic/generic_3dtk_loader.hpp +++ b/include/assets/file_parsers/generic/generic_3dtk_loader.hpp @@ -7,31 +7,63 @@ #include "glm/mat4x4.hpp" #include "util/result.hpp" #include "util/string_list.hpp" -#include "assets/prefetch_queue.hpp" +#include "assets/data_stores.hpp" +#include "assets/path_id_lookups.hpp" #include "assets/data/point_cloud_data.hpp" #include "assets/data_stores/point_cloud_store.hpp" -#include "assets/prefetch_lookup.hpp" - +namespace assets +{ template struct generic_3dtk_loader { - [[nodiscard]] static std::error_code prefetch( - const ztu::string_list& filenames, - prefetch_queue& queue + using data_type = point_cloud_data; + using store_type = point_cloud_data; + using lookup_type = point_cloud_id_lookup; + + [[nodiscard]] std::error_code prefetch( + path_id_lookups& lookups ); - [[nodiscard]] static std::error_code load( - dynamic_point_cloud_buffer& buffer, - const file_dir_list& paths, - dynamic_point_cloud_store& store, - prefetch_lookup& id_lookup, + [[nodiscard]] std::error_code load( + path_id_lookups& lookups, + data_stores& stores, bool pedantic = false ); protected: + class parser_context + { + public: + parser_context( + path_id_lookups& m_id_lookups, + data_stores& m_stores + ); + + void operator()(lookup_type::const_pointer entry) noexcept; + + protected: + void reset(); + + z3d::vertex_index find_or_push_vertex(const component_indices& vertex_comp_indices); + + [[nodiscard]] std::optional fetch_texture_id( + const std::filesystem::path& mtl_dir, + std::string_view filename, + std::string_view texture_type_name + ); + + private: + path_id_lookups* m_id_lookups; + data_stores* m_stores; + data_type m_mesh{}; + std::vector m_position_buffer{}; + std::vector m_normal_buffer{}; + std::vector m_tex_coord_buffer{}; + std::unordered_map m_vertex_comp_indices_to_vertex_index{}; + }; [[nodiscard]] static ztu::result parse_index( std::string_view filename @@ -51,8 +83,13 @@ private: const std::filesystem::path& filename, dynamic_point_cloud_buffer& point_cloud ); + +private: + std::vector m_path_buffer; }; +} + #define INCLUDE_GENERIC_3DTK_LOADER_IMPLEMENTATION -#include "../../data_parsers" +#include "assets/file_parsers/generic/generic_3dtk_loader.ipp" #undef INCLUDE_GENERIC_3DTK_LOADER_IMPLEMENTATION diff --git a/include/assets/file_parsers/mtl_parser.hpp b/include/assets/file_parsers/mtl_parser.hpp index 9350060..685ea1d 100644 --- a/include/assets/file_parsers/mtl_parser.hpp +++ b/include/assets/file_parsers/mtl_parser.hpp @@ -5,8 +5,6 @@ #include "assets/data_stores.hpp" #include "assets/path_id_lookups.hpp" -#include "assets/prefetch_lookup.hpp" -#include "assets/prefetch_queue.hpp" #include "assets/data/material_data.hpp" #include "assets/data/material_library_data.hpp" #include "assets/data_stores/material_store.hpp" @@ -50,14 +48,35 @@ struct mtl_parser ); protected: + class prefetcher_context + { + public: + prefetcher_context( + path_id_lookups& lookups + ); + + void operator()(lookup_type::const_pointer entry) noexcept; + + protected: + + [[nodiscard]] std::optional fetch_texture_id( + const std::filesystem::path& mtl_dir, + std::string_view filename, + std::string_view texture_type_name + ); + + private: + path_id_lookups* m_lookups; + std::vector m_buffer{}; + }; + + class parser_context { public: parser_context( - const texture_id_lookup& texture_id_lookup, - material_id_lookup& material_id_lookup, - material_store& material_store, - store_type& store + path_id_lookups& lookups, + data_stores& stores ); void operator()(lookup_type::const_pointer entry) noexcept; @@ -72,21 +91,11 @@ protected: ); private: - const texture_id_lookup* m_texture_id_lookup; - material_id_lookup* m_material_id_lookup; - material_store* m_material_store; - store_type* m_store; + path_id_lookups* m_lookups; + data_stores* m_stores; data_type m_buffer{}; }; - static void find_textures( - std::span buffer, - std::filesystem::path& path_buffer, - const std::filesystem::path& base_directory, - std::ifstream& in, - ztu::string_list& texture_filenames - ); - private: std::vector m_path_buffer; }; diff --git a/include/assets/file_parsers/obj_loader.hpp b/include/assets/file_parsers/obj_parser.hpp similarity index 50% rename from include/assets/file_parsers/obj_loader.hpp rename to include/assets/file_parsers/obj_parser.hpp index 3d18dc8..00266da 100755 --- a/include/assets/file_parsers/obj_loader.hpp +++ b/include/assets/file_parsers/obj_parser.hpp @@ -6,9 +6,10 @@ #include "assets/data/mesh_data.hpp" #include "assets/data_stores.hpp" #include "assets/path_id_lookups.hpp" -#include +#include +#include "util/array_hash.hpp" -namespace assets::obj_loader_error +namespace assets::obj_parser_error { enum class codes { ok = 0, @@ -27,7 +28,7 @@ enum class codes { namespace assets { -struct obj_loader +struct obj_parser { static constexpr auto name = std::string_view("obj"); using data_type = mesh_data; @@ -46,28 +47,28 @@ struct obj_loader ); protected: - struct indexed_vertex_type + using component_indices = std::array; + + class prefetcher_context { - z3d::index_triangle vertex; - z3d::vertex_index buffer_index; + public: + prefetcher_context( + path_id_lookups& id_lookups + ); - friend auto operator<=>(const indexed_vertex_type& a, const indexed_vertex_type& b) { - return a.vertex <=> b.vertex; - } + void operator()(lookup_type::const_pointer entry) noexcept; - bool operator==(const indexed_vertex_type& other) const noexcept { - return other.vertex == vertex; - } + private: + path_id_lookups* m_id_lookups; + std::vector m_buffer{}; }; class parser_context { public: parser_context( - const texture_id_lookup& texture_id_lookup, - material_id_lookup& material_id_lookup, - material_store& material_store, - store_type& store + path_id_lookups& m_id_lookups, + data_stores& m_stores ); void operator()(lookup_type::const_pointer entry) noexcept; @@ -75,6 +76,8 @@ protected: protected: void reset(); + z3d::vertex_index find_or_push_vertex(const component_indices& vertex_comp_indices); + [[nodiscard]] std::optional fetch_texture_id( const std::filesystem::path& mtl_dir, std::string_view filename, @@ -82,34 +85,16 @@ protected: ); private: - const path_id_lookups* m_id_lookups; + path_id_lookups* m_id_lookups; data_stores* m_stores; - data_type m_buffer{}; - data_type m_read_buffer{}; - std::set vertex_ids{}; + data_type m_mesh{}; + std::vector m_position_buffer{}; + std::vector m_normal_buffer{}; + std::vector m_tex_coord_buffer{}; + std::unordered_map m_vertex_comp_indices_to_vertex_index{}; }; - - - - static void find_materials( - std::span buffer, - std::filesystem::path& path_buffer, - const std::filesystem::path& base_directory, - std::ifstream& in, - ztu::string_list& material_filenames - ); - - [[nodiscard]] static std::error_code obj_loader::parse_file( - dynamic_mesh_buffer& read_buffer, - dynamic_mesh_buffer& mesh_buffer, - std::filesystem::path& path_buffer, - const std::filesystem::path& base_directory, - std::set& vertex_ids, - std::ifstream& in, - prefetch_lookup& id_lookup, - dynamic_shader_source_store& store, - bool pedantic - ); +private: + std::vector m_path_buffer; }; } diff --git a/include/assets/file_parsers/stl_loader.hpp b/include/assets/file_parsers/stl_loader.hpp index 04e8f7f..31b8427 100644 --- a/include/assets/file_parsers/stl_loader.hpp +++ b/include/assets/file_parsers/stl_loader.hpp @@ -3,28 +3,65 @@ #include #include #include +#include #include "assets/data_stores.hpp" -#include "assets/data" -#include "../data_stores" -#include "assets/prefetch_lookup.hpp" -#include "assets/prefetch_queue.hpp" +#include "assets/data/mesh_data.hpp" +#include "assets/data_stores.hpp" +#include "assets/path_id_lookups.hpp" +#include "util/vector_hash.hpp" -struct stl_loader { +namespace assets +{ +struct stl_loader +{ static constexpr auto name = std::string_view("stl"); + using data_type = mesh_data; + using store_type = mesh_store; + using lookup_type = mesh_id_lookup; - [[nodiscard]] static std::error_code prefetch( - const file_dir_list& paths, - prefetch_queue& queue + [[nodiscard]] std::error_code prefetch( + path_id_lookups& lookups ); - [[nodiscard]] static std::error_code load( - // space stuff that has to persist - dynamic_mesh_buffer& buffer, - const file_dir_list& paths, - prefetch_lookup& id_lookup, - shader_source_store& store, + [[nodiscard]] std::error_code load( + path_id_lookups& lookups, + data_stores& stores, bool pedantic = false ); + +protected: + class parser_context + { + public: + parser_context( + path_id_lookups& m_id_lookups, + data_stores& m_stores + ); + + void operator()(lookup_type::const_pointer entry) noexcept; + + protected: + void reset(); + + z3d::vertex_index find_or_push_vertex(const component_indices& vertex_comp_indices); + + [[nodiscard]] std::optional fetch_texture_id( + const std::filesystem::path& mtl_dir, + std::string_view filename, + std::string_view texture_type_name + ); + + private: + path_id_lookups* m_id_lookups; + data_stores* m_stores; + data_type m_mesh{}; + std::unordered_map m_vertex_index_lookup{}; + }; + +private: + std::vector m_path_buffer; }; + +} diff --git a/include/util/array_hash.hpp b/include/util/array_hash.hpp new file mode 100644 index 0000000..a3fae6c --- /dev/null +++ b/include/util/array_hash.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + +template +struct std::hash> +{ + auto operator() (const std::array& key) const { + auto hasher = std::hash{}; + auto result = std::size_t{}; + for (const auto& element : key) + { + result = result * 31 + hasher(element); + } + return result; + } +}; \ No newline at end of file diff --git a/include/util/enum_bitfield_operators.hpp b/include/util/enum_bitfield_operators.hpp index 096b35b..af6a8e5 100644 --- a/include/util/enum_bitfield_operators.hpp +++ b/include/util/enum_bitfield_operators.hpp @@ -36,7 +36,7 @@ } \ \ constexpr ENUM_TYPE operator<<( \ - ENUM_TYPE& lhs, \ + ENUM_TYPE lhs, \ int shift \ ) { \ return static_cast( \ @@ -44,8 +44,17 @@ constexpr ENUM_TYPE operator<<( \ ); \ } \ \ +constexpr ENUM_TYPE operator<<( \ + ENUM_TYPE lhs, \ + std::size_t shift \ +) { \ + return static_cast( \ + static_cast>(lhs) << shift \ + ); \ +} \ + \ constexpr ENUM_TYPE operator>>( \ - ENUM_TYPE& lhs, \ + ENUM_TYPE lhs, \ int shift \ ) { \ return static_cast( \ diff --git a/include/util/file_id_lookup.hpp b/include/util/file_id_lookup.hpp index c25bde5..adfda75 100644 --- a/include/util/file_id_lookup.hpp +++ b/include/util/file_id_lookup.hpp @@ -146,5 +146,5 @@ private: } container_type m_container; - std::shared_mutex m_mutex; + mutable std::shared_mutex m_mutex; }; \ No newline at end of file diff --git a/include/util/id_type.hpp b/include/util/id_type.hpp index 72d1d59..3e8b0f2 100644 --- a/include/util/id_type.hpp +++ b/include/util/id_type.hpp @@ -8,18 +8,24 @@ namespace ztu template class id_type { +private: explicit constexpr id_type(Index index) : index{ index } {} + Index index{}; + +public: static constexpr id_type next() { static std::atomic next_index{ 1 }; return id_type{ next_index.fetch_add(1, std::memory_order_seq_cst) }; } - Index index{}; - -public: constexpr id_type() = default; + constexpr id_type(const id_type& other) : index{ other.index } {} + constexpr id_type(id_type&& other) noexcept : index{ other.index } {} + constexpr id_type& operator=(const id_type& other) { index = other.index; return *this; } + constexpr id_type& operator=(id_type&& other) noexcept { index = other.index; return *this; } + constexpr auto operator<=>(const id_type&) const = default; constexpr operator bool() const diff --git a/include/util/vector_hash.hpp b/include/util/vector_hash.hpp new file mode 100644 index 0000000..1d52f53 --- /dev/null +++ b/include/util/vector_hash.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "glm/glm.hpp" +#include + +// Hash function for Eigen matrix and vector. +// The code is from `hash_combine` function of the Boost library. See +// http://www.boost.org/doc/libs/1_55_0/doc/html/hash/reference.html#boost.hash_combine . + +template +struct std::hash> +{ + auto operator() (const glm::vec& key) const + { + auto seed = std::size_t{}; + + for (glm::length_t i{}; i != L; ++i) + { + seed ^= std::hash{}(key[i]) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + } + + return seed; + } +}; diff --git a/main.cpp b/main.cpp index 32ea714..9281507 100755 --- a/main.cpp +++ b/main.cpp @@ -1,4 +1,6 @@ -#include "viewer/instance.hpp" + +/* +*#include "viewer/instance.hpp" #include "util/logger.hpp" #include #include @@ -10,7 +12,6 @@ #include "viewer/asset_types.hpp" #include "viewer/dynamic_shader_program_loading.hpp" #include "util/logger.hpp" -/* void controller_task( int args_count, char* args[], viewer::instance* z3d, @@ -180,7 +181,7 @@ void controller_task( // TODO fix std::this_thread::sleep_for(20h); -}*/ +} void controller_task( @@ -391,7 +392,7 @@ int main(int args_count, char* args[]) { std::string progress_title = "Initializing..."; float progress_ratio = 0.0f; - /*auto controller_thread = std::thread( + auto controller_thread = std::thread( controller_task, args_count, args, @@ -400,7 +401,7 @@ int main(int args_count, char* args[]) { &progress_lock, &progress_title, &progress_ratio - );*/ + ); auto loader = viewer::asset_loader{}; @@ -429,3 +430,54 @@ int main(int args_count, char* args[]) { return EXIT_SUCCESS; } +*/ + + + +#include "assets/file_parsers/obj_parser.hpp" +#include "assets/file_parsers/mtl_parser.hpp" +#include + +int main() { + assets::path_id_lookups lookups{}; + assets::data_stores stores{}; + + lookups.meshes.try_emplace("/home/zy4n/Downloads/test.obj"); + + assets::obj_parser obj_parser{}; + assets::mtl_parser mtl_parser{}; + + const auto time = [](auto title, auto&& f) + { + namespace chr = std::chrono; + using clock = chr::high_resolution_clock; + using floating_ms = chr::duration; + + const auto begin = clock::now(); + + f(); + + const auto end = clock::now(); + + const auto ms = chr::duration_cast(end - begin).count(); + + std::cout << title << ": " << ms << "ms" << std::endl; + }; + + time("obj prefetch", [&] { + std::ignore = obj_parser.prefetch(lookups); + }); + + time("mtl prefetch", [&] { + std::ignore = mtl_parser.prefetch(lookups); + }); + + time("mtl parsing", [&] { + std::ignore = mtl_parser.load(lookups, stores); + }); + + time("obj parsing", [&] { + std::ignore = obj_parser.load(lookups, stores); + }); + +} \ No newline at end of file diff --git a/source/assets/data/material_data.ipp b/source/assets/data/material_data.ipp index 00ca2cb..c43a41f 100644 --- a/source/assets/data/material_data.ipp +++ b/source/assets/data/material_data.ipp @@ -45,7 +45,7 @@ inline std::optional& assets::materi } inline std::optional& assets::material_data::bump_texture_id() { - return std::get(components); } inline const std::optional& assets::material_data::specular_filter() const diff --git a/source/assets/data/mesh_data.ipp b/source/assets/data/mesh_data.ipp index e416e92..9438abf 100644 --- a/source/assets/data/mesh_data.ipp +++ b/source/assets/data/mesh_data.ipp @@ -32,7 +32,7 @@ inline std::vector& assets::mesh_data::triangles() return m_triangles; } -inline auto& assets::mesh_data::material() +inline assets::material_id& assets::mesh_data::material() { return m_material_id; } @@ -62,12 +62,12 @@ inline const std::vector& assets::m return std::get(component_arrays); } -inline const std::vector& assets::mesh_data::triangles() const +inline const std::vector& assets::mesh_data::triangles() const { return m_triangles; } -inline const auto& assets::mesh_data::material() const +inline const assets::material_id& assets::mesh_data::material() const { return m_material_id; } diff --git a/source/assets/data/point_cloud_data.ipp b/source/assets/data/point_cloud_data.ipp index 83fe3f2..4421442 100644 --- a/source/assets/data/point_cloud_data.ipp +++ b/source/assets/data/point_cloud_data.ipp @@ -5,42 +5,42 @@ inline std::vector& assets::point_cloud_data::positions() { - return std::get(vertices); + return std::get(component_arrays); } inline std::vector& assets::point_cloud_data::normals() { - return std::get(vertices); + return std::get(component_arrays); } inline std::vector& assets::point_cloud_data::colors() { - return std::get(vertices); + return std::get(component_arrays); } inline std::vector& assets::point_cloud_data::reflectances() { - return std::get(vertices); + return std::get(component_arrays); } inline const std::vector& assets::point_cloud_data::positions() const { - return std::get(vertices); + return std::get(component_arrays); } inline const std::vector& assets::point_cloud_data::normals() const { - return std::get(vertices); + return std::get(component_arrays); } inline const std::vector& assets::point_cloud_data::colors() const { - return std::get(vertices); + return std::get(component_arrays); } inline const std::vector& assets::point_cloud_data::reflectances() const { - return std::get(vertices); + return std::get(component_arrays); } inline void assets::point_cloud_data::clear() diff --git a/source/assets/data_stores/generic/generic_basic_store.ipp b/source/assets/data_stores/generic/generic_basic_store.ipp index fd275dd..e6db84b 100644 --- a/source/assets/data_stores/generic/generic_basic_store.ipp +++ b/source/assets/data_stores/generic/generic_basic_store.ipp @@ -242,7 +242,7 @@ typename assets::detail::generic_basic_store::iterator assets::detail::ge { return iterator{ m_ids.data(), - m_data.begin(), + m_data.data(), 0 }; } @@ -252,7 +252,7 @@ typename assets::detail::generic_basic_store::iterator assets::detail::ge { return iterator{ m_ids.data(), - m_data.begin(), + m_data.data(), m_ids.size() }; } @@ -262,7 +262,7 @@ typename assets::detail::generic_basic_store::const_iterator assets::deta { return const_iterator{ m_ids.data(), - m_data.begin(), + m_data.data(), 0 }; } @@ -272,7 +272,7 @@ typename assets::detail::generic_basic_store::const_iterator assets::deta { return const_iterator{ m_ids.data(), - m_data.begin(), + m_data.data(), m_ids.size() }; } diff --git a/source/assets/data_stores/generic/generic_material_store.ipp b/source/assets/data_stores/generic/generic_material_store.ipp index 2209bcf..05765d8 100644 --- a/source/assets/data_stores/generic/generic_material_store.ipp +++ b/source/assets/data_stores/generic/generic_material_store.ipp @@ -13,13 +13,13 @@ template assets::detail::generic_material_store_iterator::generic_material_store_iterator( id_iterator_type ids, const component_iterator_type& components, - flag_count_iterator_type flag_counts, + flag_iterator_type flags, const size_type index, const offsets_type& offsets ) : m_ids{ ids }, m_components{ components }, - m_flag_counts{ flag_counts }, + m_flags{ flags }, m_index{ index }, m_offsets{ offsets } {} @@ -31,7 +31,7 @@ typename assets::detail::generic_material_store_iterator::reference asset template assets::detail::generic_material_store_iterator& assets::detail::generic_material_store_iterator::operator++() { - adjust_offsets(std::index_sequence_for{}, 1); + calc_offsets(std::index_sequence_for{}, 1); ++m_index; return *this; } @@ -45,7 +45,7 @@ assets::detail::generic_material_store_iterator assets::detail::generic_m template assets::detail::generic_material_store_iterator& assets::detail::generic_material_store_iterator::operator--() { - adjust_offsets(std::index_sequence_for{}, -1); + calc_offsets(std::index_sequence_for{}, -1); --m_index; return *this; } @@ -60,7 +60,7 @@ assets::detail::generic_material_store_iterator assets::detail::generic_m template assets::detail::generic_material_store_iterator& assets::detail::generic_material_store_iterator::operator+=(const difference_type n) { - adjust_offsets(std::index_sequence_for{}, n); + calc_offsets(std::index_sequence_for{}, n); m_index += n; return *this; } @@ -158,14 +158,12 @@ void assets::detail::generic_material_store_iterator::calc_offsets( while (n--) { - const auto& [ flags, index_count, component_count ] = m_flag_counts[m_index]; - - std::get<0>(m_offsets) += step * index_count; + const auto flags = m_flags[m_index]; ([&] { if (is_component_enabled(flags)) { - std::get<1 + Is>(m_offsets) += step * component_count; + std::get(m_offsets) += step; } }(), ...); @@ -178,12 +176,13 @@ template typename assets::detail::generic_material_store_iterator::reference assets::detail::generic_material_store_iterator::dereference(std::index_sequence) const { - const auto& flags = m_flag_counts[m_index]; + const auto& flags = m_flags[m_index]; return std::make_pair( m_ids[m_index], material_view{ - .data = { + .component_flags = flags, + .components = { ( is_component_enabled(flags) ? std::optional{ std::get(m_components)[m_offsets[Is]] } @@ -197,7 +196,7 @@ assets::detail::generic_material_store_iterator::dereference(std::index_s template std::tuple...> assets::detail::generic_material_store>::component_iterators() { - return [&](std::index_sequence) + return [&](std::index_sequence) { return std::make_tuple(std::get(m_component_arrays).data()...); } @@ -207,7 +206,7 @@ std::tuple...> assets::detail::generic_material_store std::tuple>...> assets::detail::generic_material_store>::component_iterators() const { - return [&](std::index_sequence) + return [&](std::index_sequence) { return std::make_tuple(std::get(m_component_arrays).data()...); } @@ -218,7 +217,7 @@ template std::array>::count_type, 1 + sizeof...(Ts)> assets::detail::generic_material_store>::array_counts() const { - return [&](std::index_sequence) + return [&](std::index_sequence) { return std::array{ std::get(m_component_arrays).size()... @@ -279,35 +278,37 @@ bool assets::detail::generic_material_store>::unsafe_inser auto& dst_component_flags = m_component_flag_counts[index]; - [&](std::integer_sequence) + [&](std::index_sequence) { - const auto is_component_enabled = src_component_flags & component_flag_type{ 1 } << Is; - const auto was_component_enabled = ( - new_entry - ? static_cast(dst_component_flags & component_flag_type{ 1 } << Is) - : component_flag_type{} - ); + ([&] { + const auto is_component_enabled = static_cast(src_component_flags & component_flag_type{ 1 } << Is); + const auto was_component_enabled = ( + new_entry + ? static_cast(dst_component_flags & component_flag_type{ 1 } << Is) + : false + ); - const auto& src_component = std::get(data.components); - auto& dst_component_array = std::get(m_component_arrays); - const auto component_index = it.m_offsets[Is]; - const auto dst_component_it = dst_component_array.begin() + component_index; + const auto& src_component = std::get(data.components); + auto& dst_component_array = std::get(m_component_arrays); + const auto component_index = it.m_offsets[Is]; + const auto dst_component_it = dst_component_array.begin() + component_index; - if (is_component_enabled) - { - if (was_component_enabled) + if (is_component_enabled) { - *dst_component_it = *src_component; + if (was_component_enabled) + { + *dst_component_it = *src_component; + } + else + { + dst_component_array.insert(dst_component_it, *src_component); + } } - else + else if (was_component_enabled) { - dst_component_array.insert(dst_component_it, *src_component); + dst_component_array.erase(dst_component_it); } - } - else if (was_component_enabled) - { - dst_component_array.erase(dst_component_it); - } + }, ...); } (std::index_sequence_for{}); @@ -347,10 +348,12 @@ void assets::detail::generic_material_store>::remove(const m_ids.erase(m_ids.begin() + it.m_index); - return [&](std::index_sequence) + return [&](std::index_sequence) { - auto& component_array = std::get(m_component_arrays); - (component_array.erase(component_array.begin() + it.m_offsets[Is]), ...); + ([&] { + auto& component_array = std::get(m_component_arrays); + (component_array.erase(component_array.begin() + it.m_offsets[Is]), ...); + }, ...); } (std::index_sequence_for{}); m_component_flag_counts.erase(m_component_flag_counts.begin() + it.m_index); @@ -362,9 +365,9 @@ void assets::detail::generic_material_store>::clear() auto lock = std::unique_lock{ m_mutex }; m_ids.clear(); - [&](std::index_sequence) + [&](std::index_sequence) { - std::get(m_component_arrays).clear(); + (std::get(m_component_arrays).clear(), ...); } (std::index_sequence_for{}); m_component_flag_counts.clear(); } diff --git a/source/assets/data_stores/generic/generic_mesh_store.ipp b/source/assets/data_stores/generic/generic_mesh_store.ipp index 7a0e8d5..33821c8 100644 --- a/source/assets/data_stores/generic/generic_mesh_store.ipp +++ b/source/assets/data_stores/generic/generic_mesh_store.ipp @@ -14,7 +14,7 @@ template assets::detail::generic_mesh_store_iterator::generic_mesh_store_iterator( id_iterator_type ids, - index_iterator_type indices, + triangle_iterator_type triangles, const component_iterator_type& components, material_id_iterator_type material_ids, flag_count_iterator_type flag_counts, @@ -22,7 +22,7 @@ assets::detail::generic_mesh_store_iterator::generic_mesh_store_iterator( const offsets_type& offsets ) : m_ids{ ids }, - m_indices{ indices }, + m_triangles{ triangles }, m_components{ components }, m_material_ids{ material_ids }, m_flag_counts{ flag_counts }, @@ -37,7 +37,7 @@ typename assets::detail::generic_mesh_store_iterator::reference assets::d template assets::detail::generic_mesh_store_iterator& assets::detail::generic_mesh_store_iterator::operator++() { - adjust_offsets(std::index_sequence_for{}, 1); + calc_offsets(std::index_sequence_for{}, 1); ++m_index; return *this; } @@ -51,7 +51,7 @@ assets::detail::generic_mesh_store_iterator assets::detail::generic_mesh_ template assets::detail::generic_mesh_store_iterator& assets::detail::generic_mesh_store_iterator::operator--() { - adjust_offsets(std::index_sequence_for{}, -1); + calc_offsets(std::index_sequence_for{}, -1); --m_index; return *this; } @@ -66,7 +66,7 @@ assets::detail::generic_mesh_store_iterator assets::detail::generic_mesh_ template assets::detail::generic_mesh_store_iterator& assets::detail::generic_mesh_store_iterator::operator+=(const difference_type n) { - adjust_offsets(std::index_sequence_for{}, n); + calc_offsets(std::index_sequence_for{}, n); m_index += n; return *this; } @@ -209,7 +209,7 @@ assets::detail::generic_mesh_store_iterator::dereference(std::index_seque template std::tuple...> assets::detail::generic_mesh_store>::component_iterators() { - return [&](std::index_sequence) + return [&](std::index_sequence) { return std::make_tuple(std::get(m_component_arrays).data()...); } @@ -219,7 +219,7 @@ std::tuple...> assets::detail::generic_mesh_store std::tuple>...> assets::detail::generic_mesh_store>::component_iterators() const { - return [&](std::index_sequence) + return [&](std::index_sequence) { return std::make_tuple(std::get(m_component_arrays).data()...); } @@ -230,7 +230,7 @@ template std::array>::count_type, 1 + sizeof...(Ts)> assets::detail::generic_mesh_store>::array_counts() const { - return [&](std::index_sequence) + return [&](std::index_sequence) { return std::array{ m_triangles.size(), @@ -289,18 +289,20 @@ bool assets::detail::generic_mesh_store>::unsafe_insert(it : std::numeric_limits::max() ); - [&](std::integer_sequence) + [&](std::index_sequence) { - const auto& component_array = std::get(data.component_arrays); - if (not component_array.empty()) - { - // TODO check count - const auto component_count = static_cast(component_array.size()); - if (component_count != 0 and component_count < vertex_count) + ([&] { + const auto& component_array = std::get(data.component_arrays); + if (not component_array.empty()) { - vertex_count = component_count; + // TODO check count + const auto component_count = static_cast(component_array.size()); + if (component_count != 0 and component_count < vertex_count) + { + vertex_count = component_count; + } } - } + }, ...); } (std::index_sequence_for{}); @@ -339,27 +341,33 @@ bool assets::detail::generic_mesh_store>::unsafe_insert(it data.triangles().end() ); - [&](std::integer_sequence) + [&](std::index_sequence) { - const auto is_component_enabled = src_component_flags & component_flag_type{ 1 } << Is; - const auto was_component_enabled = ( - new_entry - ? static_cast(dst_component_flags & component_flag_type{ 1 } << Is) - : component_flag_type{} - ); + ([&] { + const auto is_component_enabled = static_cast(src_component_flags & component_flag_type{ 1 } << Is); + const auto was_component_enabled = ( + new_entry + ? static_cast(dst_component_flags & component_flag_type{ 1 } << Is) + : false + ); - const auto& src_component_array = std::get(data.component_arrays); - auto& dst_component_array = std::get(m_component_arrays); - const auto component_index = it.m_offsets[1 + Is]; - const auto dst_component_it = dst_component_array.begin() + component_index; + const auto src_component_count = is_component_enabled ? vertex_count : count_type{}; + const auto dst_component_count = was_component_enabled ? dst_vertex_count : count_type{}; - 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 - ); + const auto& src_component_array = std::get(data.component_arrays); + auto& dst_component_array = std::get(m_component_arrays); + const auto component_index = it.m_offsets[1 + Is]; + const auto dst_component_it = dst_component_array.begin() + component_index; + + + ztu::replace_range( + dst_component_array, + dst_component_it, + dst_component_it + dst_component_count, + src_component_array.begin(), + src_component_array.begin() + src_component_count + ); + }, ...); } (std::index_sequence_for{}); @@ -404,7 +412,7 @@ void assets::detail::generic_mesh_store>::remove(const ite m_component_flag_counts.erase(m_component_flag_counts.begin() + index); - [&](std::index_sequence) + [&](std::index_sequence) { ([&]{ if ( component_flags & component_flag_type{ 1 } << Is) @@ -426,9 +434,9 @@ void assets::detail::generic_mesh_store>::clear() m_ids.clear(); m_triangles.clear(); - [&](std::index_sequence) + [&](std::index_sequence) { - std::get(m_component_arrays).clear(); + (std::get(m_component_arrays).clear(), ...); } (std::index_sequence_for{}); m_component_flag_counts.clear(); m_material_ids.clear(); diff --git a/source/assets/data_stores/generic/generic_point_cloud_store.ipp b/source/assets/data_stores/generic/generic_point_cloud_store.ipp index 2bea055..0e16e3c 100644 --- a/source/assets/data_stores/generic/generic_point_cloud_store.ipp +++ b/source/assets/data_stores/generic/generic_point_cloud_store.ipp @@ -198,7 +198,7 @@ assets::detail::generic_point_cloud_store_iterator::dereference(std::inde template std::tuple...> assets::detail::generic_point_cloud_store>::component_iterators() { - return [&](std::index_sequence) + return [&](std::index_sequence) { return std::make_tuple(std::get(m_component_arrays).data()...); } @@ -208,7 +208,7 @@ std::tuple...> assets::detail::generic_point_cloud_store< template std::tuple>...> assets::detail::generic_point_cloud_store>::component_iterators() const { - return [&](std::index_sequence) + return [&](std::index_sequence) { return std::make_tuple(std::get(m_component_arrays).data()...); } @@ -219,7 +219,7 @@ template std::array>::count_type, 1 + sizeof...(Ts)> assets::detail::generic_point_cloud_store>::array_counts() const { - return [&](std::index_sequence) + return [&](std::index_sequence) { return std::array{ std::get(m_component_arrays).size()... @@ -268,18 +268,20 @@ bool assets::detail::generic_point_cloud_store>::unsafe_in : std::numeric_limits::max() ); - [&](std::integer_sequence) + [&](std::index_sequence) { - const auto& component_array = std::get(data.component_arrays); - if (not component_array.empty()) - { - // TODO check count - const auto component_count = static_cast(component_array.size()); - if (component_count != 0 and component_count < vertex_count) + ([&] { + const auto& component_array = std::get(data.component_arrays); + if (not component_array.empty()) { - vertex_count = component_count; + // TODO check count + const auto component_count = static_cast(component_array.size()); + if (component_count != 0 and component_count < vertex_count) + { + vertex_count = component_count; + } } - } + }, ...); } (std::index_sequence_for{}); @@ -305,27 +307,29 @@ bool assets::detail::generic_point_cloud_store>::unsafe_in m_component_flag_counts[index] = src_component_flag_count; } - [&](std::integer_sequence) + [&](std::index_sequence) { - const auto is_component_enabled = src_component_flags & component_flag_type{ 1 } << Is; - const auto was_component_enabled = ( - new_entry - ? static_cast(dst_component_flags & component_flag_type{ 1 } << Is) - : component_flag_type{} - ); + ([&] { + const auto is_component_enabled = src_component_flags & component_flag_type{ 1 } << Is; + const auto was_component_enabled = ( + new_entry + ? static_cast(dst_component_flags & component_flag_type{ 1 } << Is) + : component_flag_type{} + ); - const auto& src_component_array = std::get(data.component_arrays); - auto& dst_component_array = std::get(m_component_arrays); - const auto component_index = it.m_offsets[1 + Is]; - const auto dst_component_it = dst_component_array.begin() + component_index; + const auto& src_component_array = std::get(data.component_arrays); + auto& dst_component_array = std::get(m_component_arrays); + const auto component_index = it.m_offsets[1 + Is]; + const auto dst_component_it = dst_component_array.begin() + component_index; - ztu::replace_range( - dst_component_array, - dst_component_it, - dst_component_it + dst_vertex_count, - src_component_array.begin(), - src_component_array.begin() + vertex_count - ); + 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{}); @@ -368,7 +372,7 @@ void assets::detail::generic_point_cloud_store>::remove(co m_component_flag_counts.erase(m_component_flag_counts.begin() + index); - [&](std::index_sequence) + [&](std::index_sequence) { ([&]{ if ( component_flags & component_flag_type{ 1 } << Is) @@ -387,9 +391,9 @@ void assets::detail::generic_point_cloud_store>::clear() auto lock = std::unique_lock{ m_mutex }; m_ids.clear(); - [&](std::index_sequence) + [&](std::index_sequence) { - std::get(m_component_arrays).clear(); + (std::get(m_component_arrays).clear(), ...); } (std::index_sequence_for{}); m_component_flag_counts.clear(); } diff --git a/source/assets/data_stores/pose_list_store.ipp b/source/assets/data_stores/pose_list_store.ipp index 5c80edd..72d0006 100644 --- a/source/assets/data_stores/pose_list_store.ipp +++ b/source/assets/data_stores/pose_list_store.ipp @@ -27,12 +27,12 @@ assets::pose_list_store_iterator::pose_list_store_iterator( template typename assets::pose_list_store_iterator::reference assets::pose_list_store_iterator::operator*() const { - return dereference(std::index_sequence_for{}); + return dereference(); } template assets::pose_list_store_iterator& assets::pose_list_store_iterator::operator++() { - adjust_offsets(std::index_sequence_for{}, 1); + calc_offset(1); ++m_index; return *this; } @@ -46,7 +46,7 @@ assets::pose_list_store_iterator assets::pose_list_store_iterator::o template assets::pose_list_store_iterator& assets::pose_list_store_iterator::operator--() { - adjust_offsets(std::index_sequence_for{}, -1); + calc_offset(-1); --m_index; return *this; } @@ -61,7 +61,7 @@ assets::pose_list_store_iterator assets::pose_list_store_iterator::o template assets::pose_list_store_iterator& assets::pose_list_store_iterator::operator+=(const difference_type n) { - adjust_offsets(std::index_sequence_for{}, n); + calc_offset(n); m_index += n; return *this; } diff --git a/source/assets/data_stores/shader_source_store.ipp b/source/assets/data_stores/shader_source_store.ipp index fbb1561..2aeed6d 100644 --- a/source/assets/data_stores/shader_source_store.ipp +++ b/source/assets/data_stores/shader_source_store.ipp @@ -30,12 +30,12 @@ assets::shader_source_store_iterator::shader_source_store_iterator( template typename assets::shader_source_store_iterator::reference assets::shader_source_store_iterator::operator*() const { - return dereference(std::index_sequence_for{}); + return dereference(); } template assets::shader_source_store_iterator& assets::shader_source_store_iterator::operator++() { - adjust_offsets(std::index_sequence_for{}, 1); + calc_offset(1); ++m_index; return *this; } @@ -49,7 +49,7 @@ assets::shader_source_store_iterator assets::shader_source_store_iterator< template assets::shader_source_store_iterator& assets::shader_source_store_iterator::operator--() { - adjust_offsets(std::index_sequence_for{}, -1); + calc_offset(-1); --m_index; return *this; } @@ -64,7 +64,7 @@ assets::shader_source_store_iterator assets::shader_source_store_iterator< template assets::shader_source_store_iterator& assets::shader_source_store_iterator::operator+=(const difference_type n) { - adjust_offsets(std::index_sequence_for{}, n); + calc_offset(n); m_index += n; return *this; } @@ -172,7 +172,7 @@ assets::shader_source_store_iterator::dereference() const ); } -bool assets::shader_source_store::insert(const id_type id, const data_type& data) +inline bool assets::shader_source_store::insert(const id_type id, const data_type& data) { auto lock = std::unique_lock{ m_mutex }; @@ -181,10 +181,21 @@ bool assets::shader_source_store::insert(const id_type id, const data_type& data return insert(result.first, id, data); } +inline std::pair assets::shader_source_store::find(id_type id) +{ + auto lock = std::shared_lock{ m_mutex }; + return unsafe_find(id); +} -template -bool assets::shader_source_store::insert(iterator it, const id_type id, const data_type& data) +inline std::pair assets::shader_source_store::find(id_type id) const +{ + auto lock = std::shared_lock{ m_mutex }; + + return unsafe_find(id); +} + +inline bool assets::shader_source_store::unsafe_insert(iterator it, const id_type id, const data_type& data) { auto lock = std::unique_lock{ m_mutex }; @@ -223,10 +234,8 @@ bool assets::shader_source_store::insert(iterator it, const id_type id, const da return new_entry; } -inline std::pair assets::shader_source_store::find(id_type id) +inline std::pair assets::shader_source_store::unsafe_find(id_type id) { - 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; @@ -235,10 +244,8 @@ inline std::pair assets::shader_sou return { begin() + index, found }; } -inline std::pair assets::shader_source_store::find(id_type id) const +inline std::pair assets::shader_source_store::unsafe_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; @@ -251,14 +258,16 @@ 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 index = it.m_index; + + m_ids.erase(m_ids.begin() + index); const auto strings_begin = m_strings.begin() + it.m_offset; - const auto strings_end = begin + it.m_lengths[it.m_index] + sizeof('\0'); + const auto strings_end = strings_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); + m_lengths.erase(m_lengths.begin() + index); + m_metadata.erase(m_metadata.begin() + index); } void assets::shader_source_store::clear() diff --git a/source/assets/file_parsers/generic/generic_3dtk_loader.ipp b/source/assets/file_parsers/generic/generic_3dtk_loader.ipp index 6ff4dd8..a68f79d 100644 --- a/source/assets/file_parsers/generic/generic_3dtk_loader.ipp +++ b/source/assets/file_parsers/generic/generic_3dtk_loader.ipp @@ -9,6 +9,141 @@ #include "glm/gtx/euler_angles.hpp" #include #include +#include +#include + + +template +std::error_code assets::generic_3dtk_loader::prefetch( + path_id_lookups& lookups +) { + m_path_buffer.clear(); + lookups.meshes.by_extension(".3d", m_path_buffer); + + auto path_buffer = std::filesystem::path{}; + + for (const auto entry : m_path_buffer) + { + path_buffer = entry->first; + path_buffer.replace_extension(".pose"); + lookups.poses.try_emplace(path_buffer); + } + + return {}; +} + +template +std::error_code assets::generic_3dtk_loader::load( + path_id_lookups& lookups, + data_stores& stores, + bool pedantic +) { + m_path_buffer.clear(); + lookups.point_clouds.by_extension(".3d", m_path_buffer); + + std::for_each( + std::execution::parallel_unsequenced_policy{}, + m_path_buffer.begin(), + m_path_buffer.end(), + parser_context{ + lookups, + stores, + } + ); + + return {}; +} + +template +assets::generic_3dtk_loader::parser_context::parser_context( + path_id_lookups& m_id_lookups, + data_stores& m_stores +) : + m_id_lookups{ &m_id_lookups }, + m_stores{ &m_stores } +{ + constexpr auto expected_vertex_count = 8192; + m_mesh.positions().reserve(expected_vertex_count); + m_mesh.normals().reserve(expected_vertex_count); + m_mesh.colors().reserve(expected_vertex_count); + m_mesh.reflectances().reserve(expected_vertex_count); + m_mesh.tex_coords().reserve(expected_vertex_count); + m_mesh.triangles().reserve(2 * expected_vertex_count); + + m_position_buffer.reserve(expected_vertex_count); + m_normal_buffer.reserve(expected_vertex_count); + m_tex_coord_buffer.reserve(expected_vertex_count); +} + +template +void assets::generic_3dtk_loader::parser_context::reset() +{ + m_mesh.clear(); + m_position_buffer.clear(); + m_normal_buffer.clear(); + m_tex_coord_buffer.clear(); + m_vertex_comp_indices_to_vertex_index.clear(); +} + +template +void assets::generic_3dtk_loader::parser_context::operator()(lookup_type::const_pointer entry) noexcept +{ + // TODO look up pose + const auto& [ filename, id ] = *entry; + + auto in = std::ifstream{ filename }; + if (not in.is_open()) + { + ztu::logger::warn("Cannot open obj file %.", filename); + return; + } + + + std::size_t scan_index; + + if (auto res = parse_index(filename)) + { + scan_index = *res; + } + else [[unlikely]] + { + const auto error = res.error(); + ztu::logger::error( + "Error occurred while parsing scan index in filename %: [%] %", + error.category().name(), + error.message() + ); + } + + auto pose = asset_lookup.poses.find(); + + + const auto id_it = id_lookup.find(filename); + + if (id_it != id_lookup.end()) [[unlikely]] + { + return; + } + + in.open(filename); + if (in.is_open()) + { + if ((error = this->read_point_file(filename, buffer))) { + return error; + } + + this->transform_point_cloud(buffer.positions(), pose); + + const auto id = store.add(std::move(buffer)); + id_lookup.emplace_hint(id_it, filename, id); + } + else + { + ztu::logger::error("Cannot open 3dtk file %", filename); + } + + in.close(); +} template ztu::result generic_3dtk_loader::parse_index( @@ -37,35 +172,12 @@ ztu::result generic_3dtk_loader -std::error_code generic_3dtk_loader::prefetch( - const file_dir_list& paths, - prefetch_queue& queue -) { - - auto path_buffer = std::filesystem::path{}; - - for (const auto filename : paths.files) - { - path_buffer.assign(filename.begin(), filename.end()); - path_buffer.replace_extension(".pose"); - queue.uos_queue.files.push_back(path_buffer.c_str()); - } - - // TODO optimize - for (const auto directory : paths.directories) - { - queue.uos_queue.directories.push_back(directory); - } -} template -std::error_code generic_3dtk_loader::load( - dynamic_point_cloud_buffer& buffer, - const file_dir_list& paths, - prefetch_lookup& asset_lookup, - dynamic_point_cloud_store& store, - const bool pedantic +std::error_code assets::generic_3dtk_loader::load( + path_id_lookups& lookups, + data_stores& stores, + bool pedantic = false ) { namespace fs = std::filesystem; @@ -127,8 +239,6 @@ std::error_code generic_3dtk_loader::load( load_file(filename.data()); } - - for (const auto directory : paths.directories) { directory_buffer.assign(directory.begin(), directory.end()); diff --git a/source/assets/file_parsers/mtl_parser.cpp b/source/assets/file_parsers/mtl_parser.cpp index d85c6d3..c2df4f7 100644 --- a/source/assets/file_parsers/mtl_parser.cpp +++ b/source/assets/file_parsers/mtl_parser.cpp @@ -63,58 +63,47 @@ inline std::error_code make_error_code(codes e) } } // namespace mtl_loader_error +template +std::errc parse_numeric_vector(std::string_view param, z3d::vec& vec) +{ + auto it = param.begin(); + const auto end = param.end(); + + for (int i{}; i != L; ++i) + { + if (it >= end) + { + return std::errc::invalid_argument; + } + + const auto [ptr, ec] = std::from_chars(it, end, vec[i]); + + if (ec != std::errc{}) + { + return ec; + } + + it = ptr + 1; // Skip space in between components. + } + + return {}; +}; + 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; + m_path_buffer.clear(); + lookups.material_libraries.by_extension(".mtl", m_path_buffer); - auto buffer = std::vector(8 * 1024, '\0'); - - auto in = std::ifstream{}; - - auto path_buffer = fs::path{}; - auto filename_buffer = fs::path{}; - - const auto process_file = [&]() - { - in.open(filename_buffer); - if (not in.is_open()) { - ztu::logger::error("Could not open .mtl file '%'", filename_buffer); - return; + std::for_each( + std::execution::parallel_unsequenced_policy{}, + m_path_buffer.begin(), + m_path_buffer.end(), + prefetcher_context{ + lookups } - - 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 {}; } @@ -127,20 +116,14 @@ std::error_code assets::mtl_parser::load( 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 + lookups, + stores, } ); @@ -149,31 +132,169 @@ std::error_code assets::mtl_parser::load( -inline std::error_category& connector_error_category() +assets::mtl_parser::prefetcher_context::prefetcher_context( + path_id_lookups& lookups +) : + m_lookups{ &lookups } { - static assets::mtl_parser_error::category category; - return category; + m_buffer.resize(8192); } -namespace assets::mtl_parser_error +void assets::mtl_parser::prefetcher_context::operator()(lookup_type::const_pointer entry) noexcept { -inline std::error_code make_error_code(const codes e) -{ - return { static_cast(e), connector_error_category() }; -} -} // namespace mtl_loader_error + namespace fs = std::filesystem; + using namespace std::string_view_literals; + // TODO 'bump' is missing!!! + + static constexpr auto keyword = "\nmap_"sv; + + using long_postfix_type = std::array; + + static constexpr auto postfix_length = std::tuple_size_v; + + static constexpr auto make_postfix = [](const std::string_view str) static constexpr + { + auto postfix = long_postfix_type{}; + assert(str.length() >= postfix_length); + std::copy_n(str.begin(), postfix.size(), postfix.begin()); + return postfix; + }; + + static constexpr auto postfixes = std::array{ + make_postfix("d "), + make_postfix("Ka"), + make_postfix("Kd"), + make_postfix("Ks"), + make_postfix("Ns") + }; + + const auto buffer_view = std::string_view(m_buffer); + + // Add linebreak to simplify line begin search. + m_buffer.front() = '\n'; + auto leftover = std::size_t{ 1 }; + + enum class match { + exact, + overflowed, + none + }; + + const auto check_match = [](std::string_view& potential_match) static -> match + { + std::cout << '\'' << potential_match.substr(0, std::min(40ul, potential_match.size())) << '\'' << std::endl; + + if (potential_match.length() < postfix_length) + { + return match::overflowed; + } + + const auto postfix = make_postfix(potential_match); + + // Optimized for SIMD. + if (not std::ranges::contains(postfixes, postfix)) + { + return match::none; + } + + const auto long_match = postfix.back() != ' '; + + if (long_match and ( + potential_match.length() < postfix_length + sizeof(' ') or + potential_match[postfix_length] != ' ' + )) { + return match::overflowed; + } + + const auto actual_postfix_length = std::size_t{ 1 } + static_cast(long_match); + + const auto filename_begin = actual_postfix_length + sizeof(' '); + const auto filename_end = potential_match.find('\n', filename_begin); + + if (filename_end == std::string_view::npos) + { + return match::overflowed; + } + + const auto length = filename_end - filename_begin; + potential_match = potential_match.substr(filename_begin, length); + + return match::exact; + }; + + const auto& [ filename, id ] = *entry; + + auto path_buffer = fs::path{}; + const auto base_dir = fs::canonical(fs::path(filename).parent_path()); + + auto in = std::ifstream{ filename }; + if (not in.is_open()) + { + ztu::logger::warn("Cannot open obj file %.", filename); + return; + } + + do + { + // Keep some old characters to continue matching interrupted sequence. + std::copy(m_buffer.end() - leftover, m_buffer.end(), m_buffer.begin()); + + in.read(m_buffer.data() + leftover, m_buffer.size() - leftover); + + const auto str = buffer_view.substr(0, leftover + in.gcount()); + + auto pos = std::string_view::size_type{}; + while ((pos = str.find(keyword, pos)) != std::string_view::npos) + { + const auto keyword_end = pos + keyword.size(); + auto potential_match = str.substr(keyword_end); + + const auto match_type = check_match(potential_match); + + if (match_type == match::exact) + { + path_buffer.assign(potential_match); + + if (path_buffer.is_relative()) + { + path_buffer = base_dir; + path_buffer /= potential_match; + } + + m_lookups->textures.try_emplace(path_buffer); + + pos += potential_match.size(); + + leftover = 0; + } + else if (match_type == match::overflowed) + { + if (pos == 0) [[unlikely]] + { + ztu::logger::error("Ignoring string match, as it exceeds buffer size of % characters.", m_buffer.size()); + leftover = 0; + } + else + { + leftover = str.size() - pos; + } + break; + } + else + { + leftover = keyword.size(); + } + } + } while (not in.eof()); +} 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 + path_id_lookups& lookups, + data_stores& stores ) : - m_texture_id_lookup{ &texture_id_lookup }, - m_material_id_lookup{ &material_id_lookup }, - m_material_store{ &material_store }, - m_store{ &store } + m_lookups{ &lookups }, + m_stores{ &stores } { m_buffer.reserve(32); } @@ -191,6 +312,7 @@ void assets::mtl_parser::parser_context::operator()(lookup_type::const_pointer e const auto& [ filename, id ] = *entry; + // TODO unroll stuff auto in = std::ifstream{ filename }; @@ -209,11 +331,11 @@ void assets::mtl_parser::parser_context::operator()(lookup_type::const_pointer e { if (not name.empty()) { - const auto [ id_it, is_new ] = m_material_id_lookup->try_emplace(filename / name); + const auto [ id_it, is_new ] = m_lookups->materials.try_emplace(filename / name); const auto material_id = id_it->second; - m_material_store->insert(id, material); + m_stores->materials.insert(material_id, material); m_buffer.emplace(name, material_id); } @@ -223,7 +345,7 @@ void assets::mtl_parser::parser_context::operator()(lookup_type::const_pointer e const auto ec = ztu::parse_lines( in, - pedantic, + true, // TODO pedantic, ztu::make_line_parser("newmtl ", ztu::is_not_repeating, [&](const auto& param) { push_material(); @@ -298,7 +420,7 @@ void assets::mtl_parser::parser_context::operator()(lookup_type::const_pointer e }), ztu::make_line_parser("map_Ka ", ztu::is_not_repeating, [&](const auto& param) { - if (const auto texture_id = fetch_texture_id(param, "ambient filter")) + if (const auto texture_id = fetch_texture_id(base_dir, param, "ambient filter")) { material.ambient_filter_texture_id() = *texture_id; material.component_flags |= material_components::flags::ambient_filter_texture; @@ -308,7 +430,7 @@ void assets::mtl_parser::parser_context::operator()(lookup_type::const_pointer e }), ztu::make_line_parser("map_Kd ", ztu::is_not_repeating, [&](const auto& param) { - if (const auto texture_id = fetch_texture_id(param, "diffuse filter")) + if (const auto texture_id = fetch_texture_id(base_dir, param, "diffuse filter")) { material.diffuse_filter_texture_id() = *texture_id; material.component_flags |= material_components::flags::diffuse_filter_texture; @@ -318,7 +440,7 @@ void assets::mtl_parser::parser_context::operator()(lookup_type::const_pointer e }), ztu::make_line_parser("map_Ks ", ztu::is_not_repeating, [&](const auto& param) { - if (const auto texture_id = fetch_texture_id(param, "specular filter")) + if (const auto texture_id = fetch_texture_id(base_dir, param, "specular filter")) { material.specular_filter_texture_id() = *texture_id; material.component_flags |= material_components::flags::specular_filter_texture; @@ -328,7 +450,7 @@ void assets::mtl_parser::parser_context::operator()(lookup_type::const_pointer e }), ztu::make_line_parser("map_Ns ", ztu::is_not_repeating, [&](const auto& param) { - if (const auto texture_id = fetch_texture_id(param, "shininess")) + if (const auto texture_id = fetch_texture_id(base_dir, param, "shininess")) { material.shininess_texture_id() = *texture_id; material.component_flags |= material_components::flags::shininess_texture; @@ -338,7 +460,7 @@ void assets::mtl_parser::parser_context::operator()(lookup_type::const_pointer e }), ztu::make_line_parser("map_d ", ztu::is_not_repeating, [&](const auto& param) { - if (const auto texture_id = fetch_texture_id(param, "alpha")) + if (const auto texture_id = fetch_texture_id(base_dir, param, "alpha")) { material.alpha_texture_id() = *texture_id; material.component_flags |= material_components::flags::alpha_texture; @@ -348,7 +470,7 @@ void assets::mtl_parser::parser_context::operator()(lookup_type::const_pointer e }), ztu::make_line_parser("bump ", ztu::is_not_repeating, [&](const auto& param) { - if (const auto texture_id = fetch_texture_id(param, "bump")) + if (const auto texture_id = fetch_texture_id(base_dir, param, "bump")) { material.bump_texture_id() = *texture_id; material.component_flags |= material_components::flags::bump_texture; @@ -366,7 +488,7 @@ void assets::mtl_parser::parser_context::operator()(lookup_type::const_pointer e push_material(); - m_store->insert(id, m_buffer); + m_stores->material_libraries.insert(id, m_buffer); } std::optional assets::mtl_parser::parser_context::fetch_texture_id( @@ -380,8 +502,8 @@ std::optional assets::mtl_parser::parser_context::fetch_text 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()) + const auto texture_id_it = m_lookups->textures.find(texture_filename); + if (texture_id_it == m_lookups->textures.end()) { ztu::logger::warn( "%-texture at % has not been registered and can therefor not be used.", @@ -393,175 +515,3 @@ std::optional assets::mtl_parser::parser_context::fetch_text return texture_id_it->second; } - - - -template -std::errc parse_numeric_vector(std::string_view param, std::array& values) -{ - const auto end = param.end(); - auto it = param.begin(); - - for (auto& value : values) - { - if (it >= end) - { - return std::errc::invalid_argument; - } - - const auto [ptr, ec] = std::from_chars(it, end, value); - - if (ec != std::errc{}) - { - return ec; - } - - it = ptr + 1; // skip space in between components - } - - return {}; -}; - - - - -void assets::mtl_parser::find_textures( - std::span buffer, - std::filesystem::path& path_buffer, - const std::filesystem::path& base_directory, - std::ifstream& in, - ztu::string_list& texture_filenames -) { - using namespace std::string_view_literals; - - // TODO 'bump' is missing!!! - - static constexpr auto keyword = "\nmap_"sv; - - using long_postfix_type = std::array; - - static constexpr auto postfix_length = std::tuple_size_v; - - static constexpr auto make_postfix = [](const std::string_view str) static constexpr - { - auto postfix = long_postfix_type{}; - assert(str.length() >= postfix_length); - std::copy_n(str.begin(), postfix.size(), postfix.begin()); - return postfix; - }; - - static constexpr auto postfixes = std::array{ - make_postfix("d "), - make_postfix("Ka"), - make_postfix("Kd"), - make_postfix("Ks"), - make_postfix("Ns") - }; - - const auto buffer_view = std::string_view(buffer); - - // Add linebreak to simplify line begin search. - buffer.front() = '\n'; - auto leftover = std::size_t{ 1 }; - - enum class match { - exact, - overflowed, - none - }; - - const auto check_match = [](std::string_view& potential_match) static -> match - { - std::cout << '\'' << potential_match.substr(0, std::min(40ul, potential_match.size())) << '\'' << std::endl; - - if (potential_match.length() < postfix_length) - { - return match::overflowed; - } - - const auto postfix = make_postfix(potential_match); - - // Optimized for SIMD. - if (not std::ranges::contains(postfixes, postfix)) - { - return match::none; - } - - const auto long_match = postfix.back() != ' '; - - if (long_match and ( - potential_match.length() < postfix_length + sizeof(' ') or - potential_match[postfix_length] != ' ' - )) { - return match::overflowed; - } - - const auto actual_postfix_length = std::size_t{ 1 } + static_cast(long_match); - - const auto filename_begin = actual_postfix_length + sizeof(' '); - const auto filename_end = potential_match.find('\n', filename_begin); - - if (filename_end == std::string_view::npos) - { - return match::overflowed; - } - - const auto length = filename_end - filename_begin; - potential_match = potential_match.substr(filename_begin, length); - - return match::exact; - }; - - do - { - // Keep some old characters to continue matching interrupted sequence. - std::copy(buffer.end() - leftover, buffer.end(), buffer.begin()); - - in.read(buffer.data() + leftover, buffer.size() - leftover); - - const auto str = buffer_view.substr(0, leftover + in.gcount()); - - auto pos = std::string_view::size_type{}; - while ((pos = str.find(keyword, pos)) != std::string_view::npos) - { - const auto keyword_end = pos + keyword.size(); - auto potential_match = str.substr(keyword_end); - - const auto match_type = check_match(potential_match); - - if (match_type == match::exact) - { - path_buffer.assign(potential_match); - - if (path_buffer.is_relative()) - { - path_buffer = base_directory; - path_buffer /= potential_match; - } - - texture_filenames.push_back(path_buffer.c_str()); - - pos += potential_match.size(); - - leftover = 0; - } - else if (match_type == match::overflowed) - { - if (pos == 0) [[unlikely]] - { - ztu::logger::error("Ignoring string match, as it exceeds buffer size of % characters.", buffer.size()); - leftover = 0; - } - else - { - leftover = str.size() - pos; - } - break; - } - else - { - leftover = keyword.size(); - } - } - } while (not in.eof()); -} diff --git a/source/assets/file_parsers/obj_loader.cpp b/source/assets/file_parsers/obj_loader.cpp deleted file mode 100755 index 8a9c0b9..0000000 --- a/source/assets/file_parsers/obj_loader.cpp +++ /dev/null @@ -1,602 +0,0 @@ -#include "assets/file_parsers/obj_loader.hpp" - -#include -#include -#include - -#include "assets/components/mesh_vertex_components.hpp" - -#include "util/logger.hpp" -#include "util/for_each.hpp" -#include "util/line_parser.hpp" - -namespace assets::obj_loader_error -{ -struct category : std::error_category -{ - [[nodiscard]] const char* name() const noexcept override { - return "obj_loader"; - } - - [[nodiscard]] std::string message(int ev) const override - { - switch (static_cast(ev)) - { - using enum codes; - case cannot_open_file: - return "Cannot open given obj file."; - case malformed_vertex: - return "File contains malformed 'v' statement."; - case malformed_texture_coordinate: - return "File contains malformed 'vt' statement."; - case malformed_normal: - return "File contains malformed 'vn' statement."; - case malformed_face: - return "File contains malformed 'f' statement."; - case face_index_out_of_range: - return "Face index out of range."; - case unknown_line_begin: - return "Unknown obj line begin."; - case use_material_without_material_library: - return "'usemtl' statement before material library loaded."; - case unknown_material_name: - return "No matching material name found in material library."; - default: - using namespace std::string_literals; - return "unrecognized error ("s + std::to_string(ev) + ")"; - } - } -}; - -} // namespace mesh_loader_error - -inline std::error_category& obj_loader_error_category() -{ - static assets::obj_loader_error::category category; - return category; -} - -namespace assets::obj_loader_error -{ -inline std::error_code make_error_code(codes e) -{ - return { static_cast(e), obj_loader_error_category() }; -} -} // namespace mesh_loader_error - - - -assets::obj_loader::parser_context::parser_context( - const texture_id_lookup& texture_id_lookup, - material_id_lookup& material_id_lookup, - material_store& material_store, - store_type& store -) : - m_texture_id_lookup{ &texture_id_lookup }, - m_material_id_lookup{ &material_id_lookup }, - m_material_store{ &material_store }, - m_store{ &store } -{ - constexpr auto expected_vertex_count = 8192; - m_buffer.positions().reserve(expected_vertex_count); - m_buffer.normals().reserve(expected_vertex_count); - m_buffer.colors().reserve(expected_vertex_count); - m_buffer.reflectances().reserve(expected_vertex_count); - m_buffer.tex_coords().reserve(expected_vertex_count); - m_buffer.triangles().reserve(2 * expected_vertex_count); - - m_read_buffer.positions().reserve(expected_vertex_count); - m_read_buffer.normals().reserve(expected_vertex_count); - m_read_buffer.colors().reserve(expected_vertex_count); - m_read_buffer.reflectances().reserve(expected_vertex_count); - m_read_buffer.tex_coords().reserve(expected_vertex_count); - m_read_buffer.triangles().reserve(2 * expected_vertex_count); -} - -void assets::obj_loader::parser_context::reset() -{ - m_buffer.clear(); - m_read_buffer.clear(); - vertex_ids.clear(); -} - -void assets::obj_loader::parser_context::operator()(lookup_type::const_pointer entry) noexcept -{ - using obj_loader_error::codes; - using obj_loader_error::make_error_code; - namespace fs = std::filesystem; - - reset(); - - auto path_buffer = fs::path{}; - const auto base_dir = fs::canonical(fs::path(filename).parent_path()); - - // Buffers for storing the vertex component definitions. - auto& position_buffer = m_read_buffer.positions(); - auto& normal_buffer = m_read_buffer.normals(); - auto& tex_coord_buffer = m_read_buffer.tex_coords(); - - auto& positions = m_buffer.positions(); - auto& normals = m_buffer.normals(); - auto& tex_coords = m_buffer.tex_coords(); - auto& triangles = m_buffer.triangles(); - - const auto& [ filename, id ] = *entry; - - auto in = std::ifstream{ filename }; - if (not in.is_open()) - { - ztu::logger::warn("Cannot open obj file %.", filename); - return; - } - - - const auto push_mesh = [&](const bool clear_read_buffer = false) - { - if (not triangles.empty()) - { - ztu::logger::debug("Parsed % positions.", positions.size()); - ztu::logger::debug("Parsed % normals.", normals.size()); - ztu::logger::debug("Parsed % tex_coords.", tex_coords.size()); - ztu::logger::debug("Parsed % triangles.", triangles.size()); - - // Copy buffer into store and keep capacity. - m_store->insert(id, m_buffer); - } - - if (clear_read_buffer) - { - m_read_buffer.clear(); - } - - m_buffer.clear(); - vertex_ids.clear(); - }; - - const auto find_or_push_vertex = [&](const z3d::index_triangle& vertex) -> z3d::vertex_index - { - auto indexed_vid = indexed_vertex_type{ - .vertex = vertex, - .buffer_index = static_cast(positions.size()) - }; - - // Search through sorted lookup to check if index combination is unique - const auto [ id_it, unique ] = vertex_ids.insert(indexed_vid); - - if (unique) - { - const auto& [ position_index, tex_coord_index, normal_index ] = vertex; - - // If index is out of range, push default constructed value. - // Not ideal, but better than out of range indices. - - auto& position = positions.emplace_back(); - if (position_index < position_buffer.size()) - { - position = position_buffer[position_index]; - } - - auto& normal = normals.emplace_back(); - if (normal_index < normal_buffer.size()) - { - normal = normal_buffer[normal_index]; - } - - auto& tex_coord = tex_coords.emplace_back(); - if (tex_coord_index < tex_coord_buffer.size()) - { - tex_coord = tex_coord_buffer[tex_coord_index]; - } - } - - return id_it->buffer_index; - }; - - const material_library_data* curr_material_library{}; - - const auto ec = ztu::parse_lines( - in, - pedantic, - make_line_parser("v ", ztu::is_repeating, [&](const auto& param) - { - mesh_vertex_components::position position; - if (parse_numeric_vector(param, position) != std::errc{}) [[unlikely]] - { - return codes::malformed_vertex; - } - - position_buffer.push_back(position); - - return codes::ok; - }), - make_line_parser("vt ", ztu::is_repeating, [&](const auto& param) - { - mesh_vertex_components::tex_coord coord; - if (parse_numeric_vector(param, coord) != std::errc{}) [[unlikely]] - { - return codes::malformed_texture_coordinate; - } - - tex_coord_buffer.push_back(coord); - - return codes::ok; - }), - make_line_parser("vn ", ztu::is_repeating, [&](const auto& param) - { - mesh_vertex_components::normal normal; - if (parse_numeric_vector(param, normal) != std::errc{}) [[unlikely]] - { - return codes::malformed_normal; - } - - normal_buffer.push_back(normal); - - return codes::ok; - }), - make_line_parser("o ", ztu::is_not_repeating, [&](const auto&) - { - push_mesh(); // Name is currently ignored - return codes::ok; - }), - make_line_parser("f ", ztu::is_repeating, [&](const auto& param) - { - const auto begin = param.begin().base(); - const auto end = param.end().base(); - - auto vertex = z3d::index_triangle{}; - - z3d::vertex_index first_index{}, prev_index{}; - - auto vertex_count = std::size_t{}; - - for (auto it = begin; it <= end; ++it) - { - - for (auto& component_index : vertex) - { - if (it != end and *it == '/') - { - ++it; - continue; - } - - const auto [ptr, ec] = std::from_chars(it, end, component_index); - if (ec != std::errc()) [[unlikely]] - { - // Discard whole face if one index is malformed. - return codes::malformed_face; - } - - --component_index; // Convert to zero based index. - it = ptr; - - if (it == end or *it != '/') - { - break; - } - - ++it; - } - - ++vertex_count; - - if (it != end and *it != ' ') [[unlikely]] - { - return codes::malformed_face; - } - - const auto curr_index = find_or_push_vertex(vertex); - - if (vertex_count >= 3) - { - triangles.emplace_back() = { - first_index, - prev_index, - curr_index - }; - } - else if (vertex_count == 1) - { - first_index = curr_index; - } - - prev_index = curr_index; - } - - return codes::ok; - }), - make_line_parser("usemtl ", ztu::is_not_repeating, [&](const auto& param) - { - push_mesh(false); - - if (not curr_material_library) [[unlikely]] - { - return codes::use_material_without_material_library; - } - - const auto material_id_it = curr_material_library->find(param); - - if (material_id_it == curr_material_library->end()) [[unlikely]] - { - return codes::unknown_material_name; - } - - m_buffer.material() = material_id_it->second; - - return codes::ok; - }), - make_line_parser("mtllib ", ztu::is_not_repeating, [&](const auto& param) - { - path_buffer.assign(param); - - if (path_buffer.is_relative()) - { - path_buffer = base_dir; - path_buffer /= param; - } - - const auto material_library_id_it = m_id_lookups->material_libraries.find(path_buffer); - - if (material_library_id_it != m_id_lookups->material_libraries.end()) [[likely]] - { - const auto material_library_id = material_library_id_it->second; - - const auto [ it, found ] = m_stores->material_libraries.find(material_library_id); - if (found) - { - curr_material_library = &(it->second); - } - else - { - // TODO ALARM!!! - } - } - else [[unlikely]] - { - ztu::logger::warn( - "Could not find a matching material library with path '%'. Proceeding with default material.", - param - ); - curr_material_library = nullptr; - } - }) - ); - - if (ec != codes::ok) - { - const auto e = make_error_code(ec); - ztu::logger::error("Error while parsing obj file %: %", filename, e.message()); - } - - push_mesh(); -} - -void assets::obj_loader::find_materials( - std::span buffer, - std::filesystem::path& path_buffer, - const std::filesystem::path& base_directory, - std::ifstream& in, - ztu::string_list& material_filenames -) { - static constexpr auto keyword = std::string_view{ "\nmtllib " }; - - const auto buffer_view = std::string_view(buffer); - - // Add linebreak to simplify line begin search. - buffer.front() = '\n'; - auto leftover = std::size_t{ 1 }; - - do - { - // Keep some old characters to continue matching interrupted sequence. - std::copy(buffer.end() - leftover, buffer.end(), buffer.begin()); - - in.read(buffer.data() + leftover, buffer.size() - leftover); - - const auto str = buffer_view.substr(0, leftover + in.gcount()); - - leftover = keyword.size(); - - auto pos = std::string_view::size_type{}; - while ((pos = str.find(keyword, pos)) != std::string_view::npos) - { - const auto filename_begin = pos + keyword.size(); - const auto filename_end = str.find('\n', filename_begin); - - if (filename_end != std::string_view::npos) - { - const auto length = filename_end - filename_begin; - const auto filename = str.substr(filename_begin, length); - - path_buffer.assign(filename); - - if (path_buffer.is_relative()) - { - path_buffer = base_directory; - path_buffer /= filename; - } - - material_filenames.push_back(path_buffer.c_str()); - - pos = filename_end; - } - else // String match exceeds buffer. - { - if (pos == 0) [[unlikely]] - { - ztu::logger::error("Ignoring string match, as it exceeds buffer size of % characters.", buffer.size()); - leftover = 0; - } - else - { - leftover = str.size() - pos; - } - break; - } - } - } while (not in.eof()); -} - - -std::error_code assets::obj_loader::prefetch( - const file_dir_list& paths, - prefetch_queue& queue -) { - namespace fs = std::filesystem; - using assets::obj_loader_error::codes; - using assets::obj_loader_error::make_error_code; - - auto buffer = std::vector(8 * 1024, '\0'); - - auto in = std::ifstream{}; - - auto path_buffer = fs::path{}; - auto filename_buffer = fs::path{}; - - const auto process_file = [&]() - { - in.open(filename_buffer); - if (not in.is_open()) { - ztu::logger::error("Could not open .obj file '%'", filename_buffer); - return; - } - - filename_buffer.remove_filename(); - - find_materials(buffer, path_buffer, filename_buffer, in, queue.mtl_queue.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 assets::obj_loader::load( - dynamic_mesh_buffer& buffer, - const file_dir_list& paths, - prefetch_lookup& id_lookup, - dynamic_shader_source_store& store, - bool pedantic -) { - namespace fs = std::filesystem; - - auto position_buffer = buffer.positions(); - auto normal_buffer = buffer.normals(); - auto tex_coord_buffer = buffer.tex_coords(); - - auto read_buffer = dynamic_mesh_buffer{}; - auto path_buffer = fs::path{}; - auto vertex_ids = std::set{}; - auto in = std::ifstream{}; - - auto filename_buffer = fs::path{}; - - const auto process_file = [&]() - { - in.open(filename_buffer); - if (not in.is_open()) { - ztu::logger::error("Could not open .obj file '%'", filename_buffer); - return; - } - - filename_buffer.remove_filename(); - - // parse file - const auto error = parse_file( - read_buffer, - buffer, - path_buffer, - filename_buffer, - vertex_ids, - in, - id_lookup, - store, - pedantic - ); - - if (error) - { - ztu::logger::error( - "Error occurred while parsing .obj file: [%] %", - error.category().name(), - error.message() - ); - } - - 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 {}; -} - -template -std::errc parse_numeric_vector(std::string_view param, std::array& values) -{ - auto it = param.begin(); - const auto end = param.end(); - - for (auto& value : values) - { - if (it >= end) - { - return std::errc::invalid_argument; - } - - const auto [ptr, ec] = std::from_chars(it, end, value); - - if (ec != std::errc{}) - { - return ec; - } - - it = ptr + 1; // Skip space in between components. - } - - return {}; -}; diff --git a/source/assets/file_parsers/obj_parser.cpp b/source/assets/file_parsers/obj_parser.cpp new file mode 100755 index 0000000..69b399d --- /dev/null +++ b/source/assets/file_parsers/obj_parser.cpp @@ -0,0 +1,530 @@ +#include "assets/file_parsers/obj_parser.hpp" + +#include +#include +#include + +#include "assets/components/mesh_vertex_components.hpp" + +#include "util/logger.hpp" +#include "util/for_each.hpp" +#include "util/line_parser.hpp" +#include + +namespace assets::obj_parser_error +{ +struct category : std::error_category +{ + [[nodiscard]] const char* name() const noexcept override { + return "obj_loader"; + } + + [[nodiscard]] std::string message(int ev) const override + { + switch (static_cast(ev)) + { + using enum codes; + case cannot_open_file: + return "Cannot open given obj file."; + case malformed_vertex: + return "File contains malformed 'v' statement."; + case malformed_texture_coordinate: + return "File contains malformed 'vt' statement."; + case malformed_normal: + return "File contains malformed 'vn' statement."; + case malformed_face: + return "File contains malformed 'f' statement."; + case face_index_out_of_range: + return "Face index out of range."; + case unknown_line_begin: + return "Unknown obj line begin."; + case use_material_without_material_library: + return "'usemtl' statement before material library loaded."; + case unknown_material_name: + return "No matching material name found in material library."; + default: + using namespace std::string_literals; + return "unrecognized error ("s + std::to_string(ev) + ")"; + } + } +}; + +} // namespace mesh_loader_error + +inline std::error_category& obj_loader_error_category() +{ + static assets::obj_parser_error::category category; + return category; +} + +namespace assets::obj_parser_error +{ +inline std::error_code make_error_code(codes e) +{ + return { static_cast(e), obj_loader_error_category() }; +} +} // namespace mesh_loader_error + + +std::error_code assets::obj_parser::prefetch( + path_id_lookups& lookups +) { + m_path_buffer.clear(); + lookups.meshes.by_extension(".obj", m_path_buffer); + + std::for_each( + std::execution::parallel_unsequenced_policy{}, + m_path_buffer.begin(), + m_path_buffer.end(), + prefetcher_context{ + lookups + } + ); + + return {}; +} + +std::error_code assets::obj_parser::load( + path_id_lookups& lookups, + data_stores& stores, + bool pedantic +) { + m_path_buffer.clear(); + lookups.meshes.by_extension(".obj", m_path_buffer); + + std::for_each( + std::execution::parallel_unsequenced_policy{}, + m_path_buffer.begin(), + m_path_buffer.end(), + parser_context{ + lookups, + stores, + } + ); + + return {}; +} + +template +std::errc parse_numeric_vector(std::string_view param, z3d::vec& vec) +{ + auto it = param.begin(); + const auto end = param.end(); + + for (int i{}; i != L; ++i) + { + if (it >= end) + { + return std::errc::invalid_argument; + } + + const auto [ptr, ec] = std::from_chars(it, end, vec[i]); + + if (ec != std::errc{}) + { + return ec; + } + + it = ptr + 1; // Skip space in between components. + } + + return {}; +}; + + +assets::obj_parser::parser_context::parser_context( + path_id_lookups& m_id_lookups, + data_stores& m_stores +) : + m_id_lookups{ &m_id_lookups }, + m_stores{ &m_stores } +{ + constexpr auto expected_vertex_count = 8192; + m_mesh.positions().reserve(expected_vertex_count); + m_mesh.normals().reserve(expected_vertex_count); + m_mesh.colors().reserve(expected_vertex_count); + m_mesh.reflectances().reserve(expected_vertex_count); + m_mesh.tex_coords().reserve(expected_vertex_count); + m_mesh.triangles().reserve(2 * expected_vertex_count); + + m_position_buffer.reserve(expected_vertex_count); + m_normal_buffer.reserve(expected_vertex_count); + m_tex_coord_buffer.reserve(expected_vertex_count); +} + +void assets::obj_parser::parser_context::reset() +{ + m_mesh.clear(); + m_position_buffer.clear(); + m_normal_buffer.clear(); + m_tex_coord_buffer.clear(); + m_vertex_comp_indices_to_vertex_index.clear(); +} + + +void assets::obj_parser::parser_context::operator()(lookup_type::const_pointer entry) noexcept +{ + using obj_parser_error::codes; + using obj_parser_error::make_error_code; + namespace fs = std::filesystem; + + reset(); + + const auto& [ filename, id ] = *entry; + + auto path_buffer = fs::path{}; + const auto base_dir = fs::canonical(fs::path(filename).parent_path()); + + const auto push_mesh = [&](const bool clear_read_buffer = false) + { + if (not m_mesh.triangles().empty()) + { + ztu::logger::debug("parsed % positions.", m_position_buffer.size()); + ztu::logger::debug("parsed % normals.", m_normal_buffer.size()); + ztu::logger::debug("parsed % tex_coords.", m_tex_coord_buffer.size()); + + ztu::logger::debug("stored % positions.", m_mesh.positions().size()); + ztu::logger::debug("stored % normals.", m_mesh.normals().size()); + ztu::logger::debug("stored % tex_coords.", m_mesh.tex_coords().size()); + ztu::logger::debug("stored % triangles.", m_mesh.triangles().size()); + + m_stores->meshes.insert(id, m_mesh); + } + + if (clear_read_buffer) + { + m_position_buffer.clear(); + m_normal_buffer.clear(); + m_tex_coord_buffer.clear(); + } + + m_mesh.clear(); + m_vertex_comp_indices_to_vertex_index.clear(); + }; + + const material_library_data* curr_material_library{}; + + + auto in = std::ifstream{ filename }; + if (not in.is_open()) + { + ztu::logger::warn("Cannot open obj file %.", filename); + return; + } + + const auto ec = ztu::parse_lines( + in, + false, + make_line_parser("v ", ztu::is_repeating, [&](const auto& param) + { + mesh_vertex_components::position position; + if (parse_numeric_vector(param, position) != std::errc{}) [[unlikely]] + { + return codes::malformed_vertex; + } + + m_position_buffer.push_back(position); + + return codes::ok; + }), + make_line_parser("vt ", ztu::is_repeating, [&](const auto& param) + { + mesh_vertex_components::tex_coord coord; + if (parse_numeric_vector(param, coord) != std::errc{}) [[unlikely]] + { + return codes::malformed_texture_coordinate; + } + + m_tex_coord_buffer.push_back(coord); + + return codes::ok; + }), + make_line_parser("vn ", ztu::is_repeating, [&](const auto& param) + { + mesh_vertex_components::normal normal; + if (parse_numeric_vector(param, normal) != std::errc{}) [[unlikely]] + { + return codes::malformed_normal; + } + + m_normal_buffer.push_back(normal); + + return codes::ok; + }), + make_line_parser("o ", ztu::is_not_repeating, [&](const auto&) + { + push_mesh(); // Name is currently ignored + + return codes::ok; + }), + make_line_parser("f ", ztu::is_repeating, [&](const auto& param) + { + const auto begin = param.begin().base(); + const auto end = param.end().base(); + + z3d::vertex_index first_index{}, prev_index{}; + + auto vertex_count = std::size_t{}; + + for (auto it = begin; it <= end; ++it) + { + auto vertex = component_indices{}; + + for (auto& component_index : vertex) + { + if (it != end and *it == '/') + { + ++it; + continue; + } + + const auto [ptr, ec] = std::from_chars(it, end, component_index); + if (ec != std::errc()) [[unlikely]] + { + // Discard whole face if one index is malformed. + return codes::malformed_face; + } + + it = ptr; + + if (it == end or *it != '/') + { + break; + } + + ++it; + } + + ++vertex_count; + + if (it != end and *it != ' ') [[unlikely]] + { + return codes::malformed_face; + } + + const auto curr_index = find_or_push_vertex(vertex); + + if (vertex_count >= 3) + { + m_mesh.triangles().emplace_back() = { + first_index, + prev_index, + curr_index + }; + } + else if (vertex_count == 1) + { + first_index = curr_index; + } + + prev_index = curr_index; + } + + return codes::ok; + }), + make_line_parser("g ", ztu::is_not_repeating, [&](const auto& param) + { + push_mesh(false); // Name is currently ignored + + return codes::ok; + }), + make_line_parser("usemtl ", ztu::is_not_repeating, [&](const auto& param) + { + push_mesh(false); + + if (not curr_material_library) [[unlikely]] + { + return codes::use_material_without_material_library; + } + + const auto material_id_it = curr_material_library->find(param); + + if (material_id_it == curr_material_library->end()) [[unlikely]] + { + return codes::unknown_material_name; + } + + m_mesh.material() = material_id_it->second; + + return codes::ok; + }), + make_line_parser("mtllib ", ztu::is_not_repeating, [&](const auto& param) + { + path_buffer.assign(param); + + if (path_buffer.is_relative()) + { + path_buffer = base_dir; + path_buffer /= param; + } + + const auto material_library_id_it = m_id_lookups->material_libraries.find(path_buffer); + + if (material_library_id_it != m_id_lookups->material_libraries.end()) [[likely]] + { + const auto material_library_id = material_library_id_it->second; + + const auto [ it, found ] = m_stores->material_libraries.find(material_library_id); + if (found) + { + // TODO implement proper dereference operator + curr_material_library = &((*it).second); + } + else + { + ztu::logger::warn( + "Material with name '%' was not loaded and can therefor not be used.", + param + ); + } + } + else [[unlikely]] + { + ztu::logger::warn( + "No material with name '%' found in the material library.", + param + ); + curr_material_library = nullptr; + } + + return codes::ok; + }) + ); + + if (ec != codes::ok) + { + const auto e = make_error_code(ec); + ztu::logger::error("Error while parsing obj file %: %", filename, e.message()); + } + + push_mesh(); +} + + +z3d::vertex_index assets::obj_parser::parser_context::find_or_push_vertex(const component_indices& vertex_comp_indices) +{ + // If the triangle indices are new the vertex will be pushed to the end of the buffer. + const auto new_vertex_index = static_cast(m_mesh.positions().size()); + + // Search through lookup to check if index combination already exists. + const auto [ index_it, is_new ] = m_vertex_comp_indices_to_vertex_index.try_emplace( + vertex_comp_indices, + new_vertex_index + ); + + if (is_new) + { + const auto& [ position_index, tex_coord_index, normal_index ] = vertex_comp_indices; + + // If index is out of range, push default constructed value. + // Not ideal, but better than out of range indices. + // TODO let user at least know that something went wrong. + + if (position_index) + { + auto& position = m_mesh.positions().emplace_back(); + if (position_index <= m_position_buffer.size()) + { + position = m_position_buffer[position_index - 1]; + } + } + + if (normal_index) + { + auto& normal = m_mesh.normals().emplace_back(); + if (normal_index <= m_normal_buffer.size()) + { + normal = m_normal_buffer[normal_index - 1]; + } + } + + if (tex_coord_index) + { + auto& tex_coord = m_mesh.tex_coords().emplace_back(); + if (tex_coord_index <= m_tex_coord_buffer.size()) + { + tex_coord = m_tex_coord_buffer[tex_coord_index - 1]; + } + } + } + + return index_it->second; +} + +assets::obj_parser::prefetcher_context::prefetcher_context::prefetcher_context( + path_id_lookups& id_lookups +) : m_id_lookups{ &id_lookups } +{ + m_buffer.resize(8192); +} + +void assets::obj_parser::prefetcher_context::operator()(lookup_type::const_pointer entry) noexcept +{ + namespace fs = std::filesystem; + + const auto& [ filename, id ] = *entry; + + const auto base_dir = fs::canonical(fs::path(filename).parent_path()); + + const auto buffer_view = std::string_view(m_buffer); + + auto filename_buffer = std::filesystem::path{}; + auto path_buffer = std::filesystem::path{}; + + // Add linebreak to simplify line begin search. + m_buffer.front() = '\n'; + auto leftover = std::size_t{ 1 }; + + auto in = std::ifstream{ filename }; + + static constexpr auto keyword = std::string_view{ "\nmtllib " }; + + do + { + // Keep some old characters to continue matching interrupted sequence. + std::copy(m_buffer.end() - leftover, m_buffer.end(), m_buffer.begin()); + + in.read(m_buffer.data() + leftover, m_buffer.size() - leftover); + + const auto str = buffer_view.substr(0, leftover + in.gcount()); + + leftover = keyword.size(); + + auto pos = std::string_view::size_type{}; + while ((pos = str.find(keyword, pos)) != std::string_view::npos) + { + const auto filename_begin = pos + keyword.size(); + const auto filename_end = str.find('\n', filename_begin); + + if (filename_end != std::string_view::npos) + { + const auto length = filename_end - filename_begin; + + filename_buffer = str.substr(filename_begin, length); + + if (filename_buffer.is_relative()) + { + path_buffer = base_dir; + path_buffer /= filename_buffer; + } + + m_id_lookups->material_libraries.try_emplace(path_buffer); + + pos = filename_end; + } + else // String match exceeds buffer. + { + if (pos == 0) [[unlikely]] + { + ztu::logger::error("Ignoring string match, as it exceeds buffer size of % characters.", m_buffer.size()); + leftover = 0; + } + else + { + leftover = str.size() - pos; + } + break; + } + } + } while (not in.eof()); +} diff --git a/source/assets/file_parsers/stl_loader.cpp b/source/assets/file_parsers/stl_loader.cpp index a911367..1bac7e2 100644 --- a/source/assets/file_parsers/stl_loader.cpp +++ b/source/assets/file_parsers/stl_loader.cpp @@ -3,159 +3,90 @@ #include "util/binary_ifstream.hpp" #include "util/unroll_bool_template.hpp" #include "util/logger.hpp" +#include -template -std::error_code read_body( - binary_ifstream& in, - const std::uint32_t expected_triangle_count, - std::vector& positions, - std::vector& normals, - std::vector>& triangles + +std::error_code assets::stl_loader::prefetch( + path_id_lookups& lookups ) { + return {}; +} - const auto read_vector = [&in](auto& vector) -> std::error_code +std::error_code assets::stl_loader::load( + path_id_lookups& lookups, + data_stores& stores, + bool pedantic +) { + m_path_buffer.clear(); + lookups.meshes.by_extension(".stl", m_path_buffer); + + std::for_each( + std::execution::parallel_unsequenced_policy{}, + m_path_buffer.begin(), + m_path_buffer.end(), + parser_context{ + lookups, + stores, + } + ); + + return {}; +} + + +assets::stl_loader::parser_context::parser_context( + path_id_lookups& m_id_lookups, + data_stores& m_stores +) : + m_id_lookups{ &m_id_lookups }, + m_stores{ &m_stores } +{ + constexpr auto expected_vertex_count = 8192; + m_mesh.positions().reserve(expected_vertex_count); + m_mesh.normals().reserve(expected_vertex_count); + m_mesh.colors().reserve(expected_vertex_count); + m_mesh.reflectances().reserve(expected_vertex_count); + m_mesh.tex_coords().reserve(expected_vertex_count); + m_mesh.triangles().reserve(2 * expected_vertex_count); +} + +void assets::stl_loader::parser_context::reset() +{ + m_mesh.clear(); + m_vertex_index_lookup.clear(); +} + +template +std::error_code read_vector(binary_ifstream& in, z3d::vec& vector) +{ + for (int i{}; i != L; ++i) { - for (auto& component : vector) - { - float component32; - if (const auto e = in.read_ieee754(component32)) - { - return e; - } - component = component32; - } - return {}; - }; - - for (std::uint32_t i{}; i != expected_triangle_count; ++i) { - - auto normal = mesh_vertex_components::normal{}; - if constexpr (Normals) - { - if (const auto e = read_vector(normal)) - { - return e; - } - } - - auto triangle = std::array{}; - - for (auto& index : triangle) { - - auto position = mesh_vertex_components::position{}; - if (const auto e = read_vector(position)) - { - return e; - } - - // TODO implement unique insert correctly - /*// Insert vertices sorted, to efficiently remove duplicates. - const auto it = std::ranges::upper_bound(positions, position); - - // Set index before `it` is invalidated by insert. - index = it - positions.begin(); - - if (it != positions.begin() and *std::prev(it) == position) - { - --index; - } - else - { - positions.insert(it, position); - if constexpr (Normals) - { - normals.insert(normals.begin() + index, normal); - } - }*/ - - index = positions.size(); - positions.push_back(position); - - if constexpr (Normals) - { - normals.push_back(normal); - } - } - - triangles.push_back(triangle); - - // Skip attribute bytes - if (const auto e = in.skip()) + if (const auto e = in.read_ieee754(vector[i)) { return e; } } - return {}; -} +}; -std::error_code stl_loader::read_directory( - const std::filesystem::path& path, - std::vector& meshes, - mesh_vertex_components::flags enabled_mesh_vertex_componentss, - std::vector& materials, - material_component::flags enabled_material_components, - const ztu::u32 base_material_id, - bool pedantic -) { - namespace fs = std::filesystem; - if (not fs::exists(path)) { - return make_error_code(std::errc::no_such_file_or_directory); - } +void assets::stl_loader::parser_context::operator()(lookup_type::const_pointer entry) noexcept +{ + const auto& [ filename, id ] = *entry; - for (const auto& file : fs::directory_iterator{ path / "frames" }) + auto in = binary_ifstream{}; + + if (const auto e = in.open(filename, true)) { - const auto& file_path = file.path(); - - if (file_path.extension() != ".stl") - { - continue; - } - - if (const auto e = read( - file_path, - meshes, - enabled_mesh_vertex_componentss, - materials, - enabled_material_components, - base_material_id, - pedantic - )) { - ztu::logger::error( - "Error while loading stl file '%': [%] %", - file_path, - e.category().name(), - e.message() - ); - } + ztu::logger::error("Cannot open stl file %.", filename); + return; } - return {}; -} - - -std::error_code stl_loader::read( - const std::filesystem::path& filename, - std::vector& meshes, - mesh_vertex_components::flags enabled_mesh_vertex_componentss, - std::vector&, - material_component::flags, - ztu::u32, - const bool pedantic -) { - auto error = std::error_code{}; - - auto in = binary_ifstream{}; - - if ((error = in.open(filename, true))) - { - return error; - } + reset(); auto header_bytes_left = static_cast(80); - if (pedantic) + if (true) // TODO pedanatic { // Check if ASCII file was provided, these start with a specific character sequence. @@ -163,9 +94,10 @@ std::error_code stl_loader::read( auto magic_bytes = std::array{}; - if ((error = in.read(magic_bytes))) + if (const auto e = in.read(magic_bytes)) { - return error; + ztu::logger::error("Error while parsing stl magic bytes of %: %", filename, e.message()); + return; } const auto magic_string = std::string_view( @@ -175,79 +107,81 @@ std::error_code stl_loader::read( if (magic_string == ascii_magic_string) { - return std::make_error_code(std::errc::illegal_byte_sequence); + ztu::logger::error("Error while parsing stl magic bytes %: ASCII stl files are not supported.", filename); + return; } header_bytes_left -= ascii_magic_string.size(); } // Ignore (rest of) header. - if ((error = in.skip(header_bytes_left))) + if (const auto e = in.skip(header_bytes_left)) { - return error; + ztu::logger::error("Error while parsing stl header of %: %", filename, e.message()); + return; } // Read number of bytes auto expected_triangle_count = std::uint32_t{}; - if ((error = in.read(expected_triangle_count))) + if (const auto e = in.read(expected_triangle_count)) { - return error; + ztu::logger::error("Error while parsing stl triangle count %: %", filename, e.message()); + return; } // Use separate mesh for parsing, so original mesh is only overwritten // if no errors occurred. This also guarantees unused reserved memory // is freed immediately in case of an error. - auto mesh = dynamic_mesh_data{}; - auto& positions = mesh.positions(); - auto& normals = mesh.normals(); - auto& triangles = mesh.triangles(); - auto& material_id = mesh.material_id(); + auto vertex_parsing_error = std::error_code{}; - material_id = 0; // Set to default material + for (std::uint32_t i{}; i != expected_triangle_count; ++i) { - positions.reserve(expected_triangle_count * 3); - normals.reserve(expected_triangle_count); - triangles.reserve(expected_triangle_count); + mesh_vertex_components::normal normal; + if (((vertex_parsing_error = read_vector(in, normal)))) + { + break; + } - const auto normals_enabled = ( - (enabled_mesh_vertex_componentss & mesh_vertex_components::flags::normal) != mesh_vertex_components::flags::none - ); + auto triangle = z3d::index_triangle{}; - error = unroll_bool_function_template([&]() { - return read_body( - in,expected_triangle_count, - positions, - normals, - triangles - ); - }, normals_enabled); + for (auto& index : triangle) + { + mesh_vertex_components::position position; + if (((vertex_parsing_error = read_vector(in, normal)))) + { + break; + } - // Free any unused reserved memory - positions.shrink_to_fit(); - normals.shrink_to_fit(); - triangles.shrink_to_fit(); + if (const auto it = m_vertex_index_lookup.find(position); it != m_vertex_index_lookup.end()) + { + index = it->second; + } + else + { + index = m_mesh.positions().size(); + m_vertex_index_lookup.emplace_hint(it, position, index); + m_mesh.positions().emplace_back(position); + } + } - if (error) - { - return error; + m_mesh.triangles().emplace_back(triangle); + + // Skip attribute bytes + if (((vertex_parsing_error = in.skip()))) + { + break; + } } - ztu::logger::debug("Normal count: %", normals.size()); - - if (not positions.empty()) + if (vertex_parsing_error) { - mesh.components() |= mesh_vertex_components::flags::position; + ztu::logger::error("Error while parsing stl vertices in %: %", filename, vertex_parsing_error.message()); + return; } - if (not normals.empty()) - { - ztu::logger::debug("Enabling normals!!!"); - mesh.components() |= mesh_vertex_components::flags::normal; - } + m_mesh.component_flags |= mesh_vertex_components::flags::position; + m_mesh.component_flags |= mesh_vertex_components::flags::normal; +} - meshes.emplace_back(std::move(mesh)); - - return {}; -} \ No newline at end of file