Ported the obj parser.
This commit is contained in:
441
CMakeLists.txt
441
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})
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -45,6 +45,8 @@ enum class flags : z3d::u8
|
||||
using all = z3d::structure<
|
||||
position,
|
||||
normal,
|
||||
tangent,
|
||||
bi_tangent,
|
||||
tex_coord,
|
||||
color,
|
||||
reflectance
|
||||
|
||||
@@ -17,6 +17,10 @@ public:
|
||||
C component_flags;
|
||||
z3d::structure<z3d::vector<Ts>...> component_arrays{};
|
||||
|
||||
void add() {
|
||||
|
||||
}
|
||||
|
||||
protected:
|
||||
void clear_component_arrays()
|
||||
{
|
||||
|
||||
@@ -15,7 +15,7 @@ public:
|
||||
component_set() = default;
|
||||
|
||||
C component_flags{};
|
||||
z3d::structure<z3d::optional<Ts...>> components{};
|
||||
z3d::structure<z3d::optional<Ts>...> components{};
|
||||
|
||||
protected:
|
||||
void clear_components()
|
||||
|
||||
@@ -82,7 +82,7 @@ public:
|
||||
using id_type = ID;
|
||||
using container_type = std::vector<T>;
|
||||
using iterator = generic_basic_store_iterator<ID, T>;
|
||||
using const_iterator = generic_basic_store_iterator<std::add_const_t<T>...>;
|
||||
using const_iterator = generic_basic_store_iterator<ID, std::add_const_t<T>>;
|
||||
|
||||
using size_type = std::size_t;
|
||||
using data_type = T;
|
||||
|
||||
@@ -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<id_type, material_view>;
|
||||
using flag_count_type = std::tuple<component_flag_type>;
|
||||
|
||||
using id_iterator_type = id_type*;
|
||||
using component_iterator_type = std::tuple<std::add_pointer_t<Ts>...>;
|
||||
using flag_count_iterator_type = const flag_count_type*;
|
||||
using flag_iterator_type = const component_flag_type*;
|
||||
|
||||
using offsets_type = std::array<size_type, 1 + sizeof...(Ts)>;
|
||||
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<z3d::structure<Ts...>>
|
||||
{
|
||||
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;
|
||||
|
||||
|
||||
@@ -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<z3d::structure<Ts...>>
|
||||
{
|
||||
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;
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace assets
|
||||
|
||||
class pose_list_store;
|
||||
|
||||
template<typename Char>
|
||||
template<typename Pose>
|
||||
class pose_list_store_iterator
|
||||
{
|
||||
public:
|
||||
@@ -22,7 +22,7 @@ public:
|
||||
using value_type = std::pair<id_type, pose_list_view>;
|
||||
|
||||
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<char>;
|
||||
using const_iterator = pose_list_store_iterator<const char>;
|
||||
using iterator = pose_list_store_iterator<pose_data>;
|
||||
using const_iterator = pose_list_store_iterator<const pose_data>;
|
||||
using data_type = pose_list_data;
|
||||
using id_type = pose_list_id;
|
||||
|
||||
@@ -136,7 +136,7 @@ protected:
|
||||
|
||||
private:
|
||||
std::vector<id_type> m_ids;
|
||||
std::vector<char> m_poses;
|
||||
std::vector<pose_data> m_poses;
|
||||
std::vector<count_type> m_lengths;
|
||||
mutable std::shared_mutex m_mutex;
|
||||
};
|
||||
|
||||
@@ -111,7 +111,6 @@ public:
|
||||
|
||||
[[nodiscard]] std::pair<const_iterator, bool> find(id_type id) const;
|
||||
|
||||
|
||||
inline void remove(const iterator& it);
|
||||
|
||||
inline void clear();
|
||||
|
||||
@@ -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<bool Normal, bool Color, bool Reflectance>
|
||||
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<texture_id> 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<mesh_vertex_components::position> m_position_buffer{};
|
||||
std::vector<mesh_vertex_components::normal> m_normal_buffer{};
|
||||
std::vector<mesh_vertex_components::tex_coord> m_tex_coord_buffer{};
|
||||
std::unordered_map<component_indices, z3d::vertex_index> m_vertex_comp_indices_to_vertex_index{};
|
||||
};
|
||||
|
||||
[[nodiscard]] static ztu::result<pose_prefetch_lookup::index_type> 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<lookup_type::const_pointer> 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
|
||||
|
||||
@@ -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<texture_id> 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<char> 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<char> buffer,
|
||||
std::filesystem::path& path_buffer,
|
||||
const std::filesystem::path& base_directory,
|
||||
std::ifstream& in,
|
||||
ztu::string_list& texture_filenames
|
||||
);
|
||||
|
||||
private:
|
||||
std::vector<lookup_type::const_pointer> m_path_buffer;
|
||||
};
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
#include "assets/data/mesh_data.hpp"
|
||||
#include "assets/data_stores.hpp"
|
||||
#include "assets/path_id_lookups.hpp"
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#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<z3d::vertex_index, 3>;
|
||||
|
||||
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<char> 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<texture_id> 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<indexed_vertex_type> vertex_ids{};
|
||||
data_type m_mesh{};
|
||||
std::vector<mesh_vertex_components::position> m_position_buffer{};
|
||||
std::vector<mesh_vertex_components::normal> m_normal_buffer{};
|
||||
std::vector<mesh_vertex_components::tex_coord> m_tex_coord_buffer{};
|
||||
std::unordered_map<component_indices, z3d::vertex_index> m_vertex_comp_indices_to_vertex_index{};
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
static void find_materials(
|
||||
std::span<char> 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<indexed_vertex_type>& vertex_ids,
|
||||
std::ifstream& in,
|
||||
prefetch_lookup& id_lookup,
|
||||
dynamic_shader_source_store& store,
|
||||
bool pedantic
|
||||
);
|
||||
private:
|
||||
std::vector<lookup_type::const_pointer> m_path_buffer;
|
||||
};
|
||||
}
|
||||
@@ -3,28 +3,65 @@
|
||||
#include <filesystem>
|
||||
#include <system_error>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
|
||||
#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<texture_id> 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<mesh_vertex_components::position, z3d::vertex_index> m_vertex_index_lookup{};
|
||||
};
|
||||
|
||||
private:
|
||||
std::vector<lookup_type::const_pointer> m_path_buffer;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
18
include/util/array_hash.hpp
Normal file
18
include/util/array_hash.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
template<class T, size_t N>
|
||||
struct std::hash<std::array<T, N>>
|
||||
{
|
||||
auto operator() (const std::array<T, N>& key) const {
|
||||
auto hasher = std::hash<T>{};
|
||||
auto result = std::size_t{};
|
||||
for (const auto& element : key)
|
||||
{
|
||||
result = result * 31 + hasher(element);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
@@ -36,7 +36,7 @@
|
||||
} \
|
||||
\
|
||||
constexpr ENUM_TYPE operator<<( \
|
||||
ENUM_TYPE& lhs, \
|
||||
ENUM_TYPE lhs, \
|
||||
int shift \
|
||||
) { \
|
||||
return static_cast<ENUM_TYPE>( \
|
||||
@@ -44,8 +44,17 @@ constexpr ENUM_TYPE operator<<( \
|
||||
); \
|
||||
} \
|
||||
\
|
||||
constexpr ENUM_TYPE operator<<( \
|
||||
ENUM_TYPE lhs, \
|
||||
std::size_t shift \
|
||||
) { \
|
||||
return static_cast<ENUM_TYPE>( \
|
||||
static_cast<std::underlying_type_t<ENUM_TYPE>>(lhs) << shift \
|
||||
); \
|
||||
} \
|
||||
\
|
||||
constexpr ENUM_TYPE operator>>( \
|
||||
ENUM_TYPE& lhs, \
|
||||
ENUM_TYPE lhs, \
|
||||
int shift \
|
||||
) { \
|
||||
return static_cast<ENUM_TYPE>( \
|
||||
|
||||
@@ -146,5 +146,5 @@ private:
|
||||
}
|
||||
|
||||
container_type m_container;
|
||||
std::shared_mutex m_mutex;
|
||||
mutable std::shared_mutex m_mutex;
|
||||
};
|
||||
@@ -8,18 +8,24 @@ namespace ztu
|
||||
template<typename Index, int ID>
|
||||
class id_type
|
||||
{
|
||||
private:
|
||||
explicit constexpr id_type(Index index) : index{ index } {}
|
||||
|
||||
Index index{};
|
||||
|
||||
public:
|
||||
static constexpr id_type next()
|
||||
{
|
||||
static std::atomic<Index> 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
|
||||
|
||||
24
include/util/vector_hash.hpp
Normal file
24
include/util/vector_hash.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "glm/glm.hpp"
|
||||
#include <memory>
|
||||
|
||||
// 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<glm::length_t L, typename T, glm::qualifier Q>
|
||||
struct std::hash<glm::vec<L, T, Q>>
|
||||
{
|
||||
auto operator() (const glm::vec<L, T, Q>& key) const
|
||||
{
|
||||
auto seed = std::size_t{};
|
||||
|
||||
for (glm::length_t i{}; i != L; ++i)
|
||||
{
|
||||
seed ^= std::hash<T>{}(key[i]) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
}
|
||||
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
62
main.cpp
62
main.cpp
@@ -1,4 +1,6 @@
|
||||
#include "viewer/instance.hpp"
|
||||
|
||||
/*
|
||||
*#include "viewer/instance.hpp"
|
||||
#include "util/logger.hpp"
|
||||
#include <condition_variable>
|
||||
#include <thread>
|
||||
@@ -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 <iostream>
|
||||
|
||||
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<double, std::milli>;
|
||||
|
||||
const auto begin = clock::now();
|
||||
|
||||
f();
|
||||
|
||||
const auto end = clock::now();
|
||||
|
||||
const auto ms = chr::duration_cast<floating_ms>(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);
|
||||
});
|
||||
|
||||
}
|
||||
@@ -45,7 +45,7 @@ inline std::optional<assets::material_components::alpha_texture>& assets::materi
|
||||
}
|
||||
inline std::optional<assets::material_components::bump_texture>& assets::material_data::bump_texture_id()
|
||||
{
|
||||
return std::get<material_components::indices::bump_texture(components);
|
||||
return std::get<material_components::indices::bump_texture>(components);
|
||||
}
|
||||
|
||||
inline const std::optional<assets::material_components::specular_filter>& assets::material_data::specular_filter() const
|
||||
|
||||
@@ -32,7 +32,7 @@ inline std::vector<z3d::index_triangle>& 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::mesh_vertex_components::reflectance>& assets::m
|
||||
return std::get<mesh_vertex_components::indices::reflectance>(component_arrays);
|
||||
}
|
||||
|
||||
inline const std::vector<assets::mesh_data::triangle_type>& assets::mesh_data::triangles() const
|
||||
inline const std::vector<z3d::index_triangle>& 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;
|
||||
}
|
||||
|
||||
@@ -5,42 +5,42 @@
|
||||
|
||||
inline std::vector<assets::point_cloud_vertex_components::position>& assets::point_cloud_data::positions()
|
||||
{
|
||||
return std::get<point_cloud_vertex_components::indices::position>(vertices);
|
||||
return std::get<point_cloud_vertex_components::indices::position>(component_arrays);
|
||||
}
|
||||
|
||||
inline std::vector<assets::point_cloud_vertex_components::normal>& assets::point_cloud_data::normals()
|
||||
{
|
||||
return std::get<point_cloud_vertex_components::indices::normal>(vertices);
|
||||
return std::get<point_cloud_vertex_components::indices::normal>(component_arrays);
|
||||
}
|
||||
|
||||
inline std::vector<assets::point_cloud_vertex_components::color>& assets::point_cloud_data::colors()
|
||||
{
|
||||
return std::get<point_cloud_vertex_components::indices::color>(vertices);
|
||||
return std::get<point_cloud_vertex_components::indices::color>(component_arrays);
|
||||
}
|
||||
|
||||
inline std::vector<assets::point_cloud_vertex_components::reflectance>& assets::point_cloud_data::reflectances()
|
||||
{
|
||||
return std::get<point_cloud_vertex_components::indices::reflectance>(vertices);
|
||||
return std::get<point_cloud_vertex_components::indices::reflectance>(component_arrays);
|
||||
}
|
||||
|
||||
inline const std::vector<assets::point_cloud_vertex_components::position>& assets::point_cloud_data::positions() const
|
||||
{
|
||||
return std::get<point_cloud_vertex_components::indices::position>(vertices);
|
||||
return std::get<point_cloud_vertex_components::indices::position>(component_arrays);
|
||||
}
|
||||
|
||||
inline const std::vector<assets::point_cloud_vertex_components::normal>& assets::point_cloud_data::normals() const
|
||||
{
|
||||
return std::get<point_cloud_vertex_components::indices::normal>(vertices);
|
||||
return std::get<point_cloud_vertex_components::indices::normal>(component_arrays);
|
||||
}
|
||||
|
||||
inline const std::vector<assets::point_cloud_vertex_components::color>& assets::point_cloud_data::colors() const
|
||||
{
|
||||
return std::get<point_cloud_vertex_components::indices::color>(vertices);
|
||||
return std::get<point_cloud_vertex_components::indices::color>(component_arrays);
|
||||
}
|
||||
|
||||
inline const std::vector<assets::point_cloud_vertex_components::reflectance>& assets::point_cloud_data::reflectances() const
|
||||
{
|
||||
return std::get<point_cloud_vertex_components::indices::reflectance>(vertices);
|
||||
return std::get<point_cloud_vertex_components::indices::reflectance>(component_arrays);
|
||||
}
|
||||
|
||||
inline void assets::point_cloud_data::clear()
|
||||
|
||||
@@ -242,7 +242,7 @@ typename assets::detail::generic_basic_store<ID, T>::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<ID, T>::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<ID, T>::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<ID, T>::const_iterator assets::deta
|
||||
{
|
||||
return const_iterator{
|
||||
m_ids.data(),
|
||||
m_data.begin(),
|
||||
m_data.data(),
|
||||
m_ids.size()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,13 +13,13 @@ template<typename... Ts>
|
||||
assets::detail::generic_material_store_iterator<Ts...>::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<Ts...>::reference asset
|
||||
|
||||
template<typename... Ts>
|
||||
assets::detail::generic_material_store_iterator<Ts...>& assets::detail::generic_material_store_iterator<Ts...>::operator++() {
|
||||
adjust_offsets(std::index_sequence_for<Ts...>{}, 1);
|
||||
calc_offsets(std::index_sequence_for<Ts...>{}, 1);
|
||||
++m_index;
|
||||
return *this;
|
||||
}
|
||||
@@ -45,7 +45,7 @@ assets::detail::generic_material_store_iterator<Ts...> assets::detail::generic_m
|
||||
|
||||
template<typename... Ts>
|
||||
assets::detail::generic_material_store_iterator<Ts...>& assets::detail::generic_material_store_iterator<Ts...>::operator--() {
|
||||
adjust_offsets(std::index_sequence_for<Ts...>{}, -1);
|
||||
calc_offsets(std::index_sequence_for<Ts...>{}, -1);
|
||||
--m_index;
|
||||
return *this;
|
||||
}
|
||||
@@ -60,7 +60,7 @@ assets::detail::generic_material_store_iterator<Ts...> assets::detail::generic_m
|
||||
template<typename... Ts>
|
||||
assets::detail::generic_material_store_iterator<Ts...>& assets::detail::generic_material_store_iterator<Ts...>::operator+=(const difference_type n)
|
||||
{
|
||||
adjust_offsets(std::index_sequence_for<Ts...>{}, n);
|
||||
calc_offsets(std::index_sequence_for<Ts...>{}, n);
|
||||
m_index += n;
|
||||
return *this;
|
||||
}
|
||||
@@ -158,14 +158,12 @@ void assets::detail::generic_material_store_iterator<Ts...>::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<Is>(flags))
|
||||
{
|
||||
std::get<1 + Is>(m_offsets) += step * component_count;
|
||||
std::get<Is>(m_offsets) += step;
|
||||
}
|
||||
}(), ...);
|
||||
|
||||
@@ -178,12 +176,13 @@ template<std::size_t... Is>
|
||||
typename assets::detail::generic_material_store_iterator<Ts...>::reference
|
||||
assets::detail::generic_material_store_iterator<Ts...>::dereference(std::index_sequence<Is...>) 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<Is>(flags)
|
||||
? std::optional{ std::get<Is>(m_components)[m_offsets[Is]] }
|
||||
@@ -197,7 +196,7 @@ assets::detail::generic_material_store_iterator<Ts...>::dereference(std::index_s
|
||||
template<typename... Ts>
|
||||
std::tuple<std::add_pointer_t<Ts>...> assets::detail::generic_material_store<z3d::structure<Ts...>>::component_iterators()
|
||||
{
|
||||
return [&]<auto... Is>(std::index_sequence<Is>)
|
||||
return [&]<auto... Is>(std::index_sequence<Is...>)
|
||||
{
|
||||
return std::make_tuple(std::get<Is>(m_component_arrays).data()...);
|
||||
}
|
||||
@@ -207,7 +206,7 @@ std::tuple<std::add_pointer_t<Ts>...> assets::detail::generic_material_store<z3d
|
||||
template<typename... Ts>
|
||||
std::tuple<std::add_pointer_t<std::add_const_t<Ts>>...> assets::detail::generic_material_store<z3d::structure<Ts...>>::component_iterators() const
|
||||
{
|
||||
return [&]<auto... Is>(std::index_sequence<Is>)
|
||||
return [&]<auto... Is>(std::index_sequence<Is...>)
|
||||
{
|
||||
return std::make_tuple(std::get<Is>(m_component_arrays).data()...);
|
||||
}
|
||||
@@ -218,7 +217,7 @@ template<typename... Ts>
|
||||
std::array<typename assets::detail::generic_material_store<z3d::structure<Ts...>>::count_type, 1 + sizeof...(Ts)>
|
||||
assets::detail::generic_material_store<z3d::structure<Ts...>>::array_counts() const
|
||||
{
|
||||
return [&]<auto... Is>(std::index_sequence<Is>)
|
||||
return [&]<auto... Is>(std::index_sequence<Is...>)
|
||||
{
|
||||
return std::array{
|
||||
std::get<Is>(m_component_arrays).size()...
|
||||
@@ -279,13 +278,14 @@ bool assets::detail::generic_material_store<z3d::structure<Ts...>>::unsafe_inser
|
||||
|
||||
auto& dst_component_flags = m_component_flag_counts[index];
|
||||
|
||||
[&]<auto... Is>(std::integer_sequence<Is...>)
|
||||
[&]<auto... Is>(std::index_sequence<Is...>)
|
||||
{
|
||||
const auto is_component_enabled = src_component_flags & component_flag_type{ 1 } << Is;
|
||||
([&] {
|
||||
const auto is_component_enabled = static_cast<bool>(src_component_flags & component_flag_type{ 1 } << Is);
|
||||
const auto was_component_enabled = (
|
||||
new_entry
|
||||
? static_cast<bool>(dst_component_flags & component_flag_type{ 1 } << Is)
|
||||
: component_flag_type{}
|
||||
: false
|
||||
);
|
||||
|
||||
const auto& src_component = std::get<Is>(data.components);
|
||||
@@ -308,6 +308,7 @@ bool assets::detail::generic_material_store<z3d::structure<Ts...>>::unsafe_inser
|
||||
{
|
||||
dst_component_array.erase(dst_component_it);
|
||||
}
|
||||
}, ...);
|
||||
}
|
||||
(std::index_sequence_for<Ts...>{});
|
||||
|
||||
@@ -347,10 +348,12 @@ void assets::detail::generic_material_store<z3d::structure<Ts...>>::remove(const
|
||||
|
||||
m_ids.erase(m_ids.begin() + it.m_index);
|
||||
|
||||
return [&]<auto... Is>(std::index_sequence<Is>)
|
||||
return [&]<auto... Is>(std::index_sequence<Is...>)
|
||||
{
|
||||
([&] {
|
||||
auto& component_array = std::get<Is>(m_component_arrays);
|
||||
(component_array.erase(component_array.begin() + it.m_offsets[Is]), ...);
|
||||
}, ...);
|
||||
} (std::index_sequence_for<Ts...>{});
|
||||
|
||||
m_component_flag_counts.erase(m_component_flag_counts.begin() + it.m_index);
|
||||
@@ -362,9 +365,9 @@ void assets::detail::generic_material_store<z3d::structure<Ts...>>::clear()
|
||||
auto lock = std::unique_lock{ m_mutex };
|
||||
|
||||
m_ids.clear();
|
||||
[&]<auto... Is>(std::index_sequence<Is>)
|
||||
[&]<auto... Is>(std::index_sequence<Is...>)
|
||||
{
|
||||
std::get<Is>(m_component_arrays).clear();
|
||||
(std::get<Is>(m_component_arrays).clear(), ...);
|
||||
} (std::index_sequence_for<Ts...>{});
|
||||
m_component_flag_counts.clear();
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
template<typename... Ts>
|
||||
assets::detail::generic_mesh_store_iterator<Ts...>::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<Ts...>::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<Ts...>::reference assets::d
|
||||
|
||||
template<typename... Ts>
|
||||
assets::detail::generic_mesh_store_iterator<Ts...>& assets::detail::generic_mesh_store_iterator<Ts...>::operator++() {
|
||||
adjust_offsets(std::index_sequence_for<Ts...>{}, 1);
|
||||
calc_offsets(std::index_sequence_for<Ts...>{}, 1);
|
||||
++m_index;
|
||||
return *this;
|
||||
}
|
||||
@@ -51,7 +51,7 @@ assets::detail::generic_mesh_store_iterator<Ts...> assets::detail::generic_mesh_
|
||||
|
||||
template<typename... Ts>
|
||||
assets::detail::generic_mesh_store_iterator<Ts...>& assets::detail::generic_mesh_store_iterator<Ts...>::operator--() {
|
||||
adjust_offsets(std::index_sequence_for<Ts...>{}, -1);
|
||||
calc_offsets(std::index_sequence_for<Ts...>{}, -1);
|
||||
--m_index;
|
||||
return *this;
|
||||
}
|
||||
@@ -66,7 +66,7 @@ assets::detail::generic_mesh_store_iterator<Ts...> assets::detail::generic_mesh_
|
||||
template<typename... Ts>
|
||||
assets::detail::generic_mesh_store_iterator<Ts...>& assets::detail::generic_mesh_store_iterator<Ts...>::operator+=(const difference_type n)
|
||||
{
|
||||
adjust_offsets(std::index_sequence_for<Ts...>{}, n);
|
||||
calc_offsets(std::index_sequence_for<Ts...>{}, n);
|
||||
m_index += n;
|
||||
return *this;
|
||||
}
|
||||
@@ -209,7 +209,7 @@ assets::detail::generic_mesh_store_iterator<Ts...>::dereference(std::index_seque
|
||||
template<typename... Ts>
|
||||
std::tuple<std::add_pointer_t<Ts>...> assets::detail::generic_mesh_store<z3d::structure<Ts...>>::component_iterators()
|
||||
{
|
||||
return [&]<auto... Is>(std::index_sequence<Is>)
|
||||
return [&]<auto... Is>(std::index_sequence<Is...>)
|
||||
{
|
||||
return std::make_tuple(std::get<Is>(m_component_arrays).data()...);
|
||||
}
|
||||
@@ -219,7 +219,7 @@ std::tuple<std::add_pointer_t<Ts>...> assets::detail::generic_mesh_store<z3d::st
|
||||
template<typename... Ts>
|
||||
std::tuple<std::add_pointer_t<std::add_const_t<Ts>>...> assets::detail::generic_mesh_store<z3d::structure<Ts...>>::component_iterators() const
|
||||
{
|
||||
return [&]<auto... Is>(std::index_sequence<Is>)
|
||||
return [&]<auto... Is>(std::index_sequence<Is...>)
|
||||
{
|
||||
return std::make_tuple(std::get<Is>(m_component_arrays).data()...);
|
||||
}
|
||||
@@ -230,7 +230,7 @@ template<typename... Ts>
|
||||
std::array<typename assets::detail::generic_mesh_store<z3d::structure<Ts...>>::count_type, 1 + sizeof...(Ts)>
|
||||
assets::detail::generic_mesh_store<z3d::structure<Ts...>>::array_counts() const
|
||||
{
|
||||
return [&]<auto... Is>(std::index_sequence<Is>)
|
||||
return [&]<auto... Is>(std::index_sequence<Is...>)
|
||||
{
|
||||
return std::array{
|
||||
m_triangles.size(),
|
||||
@@ -289,8 +289,9 @@ bool assets::detail::generic_mesh_store<z3d::structure<Ts...>>::unsafe_insert(it
|
||||
: std::numeric_limits<count_type>::max()
|
||||
);
|
||||
|
||||
[&]<auto... Is>(std::integer_sequence<Is...>)
|
||||
[&]<auto... Is>(std::index_sequence<Is...>)
|
||||
{
|
||||
([&] {
|
||||
const auto& component_array = std::get<Is>(data.component_arrays);
|
||||
if (not component_array.empty())
|
||||
{
|
||||
@@ -301,6 +302,7 @@ bool assets::detail::generic_mesh_store<z3d::structure<Ts...>>::unsafe_insert(it
|
||||
vertex_count = component_count;
|
||||
}
|
||||
}
|
||||
}, ...);
|
||||
}
|
||||
(std::index_sequence_for<Ts...>{});
|
||||
|
||||
@@ -339,27 +341,33 @@ bool assets::detail::generic_mesh_store<z3d::structure<Ts...>>::unsafe_insert(it
|
||||
data.triangles().end()
|
||||
);
|
||||
|
||||
[&]<auto... Is>(std::integer_sequence<Is...>)
|
||||
[&]<auto... Is>(std::index_sequence<Is...>)
|
||||
{
|
||||
const auto is_component_enabled = src_component_flags & component_flag_type{ 1 } << Is;
|
||||
([&] {
|
||||
const auto is_component_enabled = static_cast<bool>(src_component_flags & component_flag_type{ 1 } << Is);
|
||||
const auto was_component_enabled = (
|
||||
new_entry
|
||||
? static_cast<bool>(dst_component_flags & component_flag_type{ 1 } << Is)
|
||||
: component_flag_type{}
|
||||
: false
|
||||
);
|
||||
|
||||
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{};
|
||||
|
||||
const auto& src_component_array = std::get<Is>(data.component_arrays);
|
||||
auto& dst_component_array = std::get<Is>(m_component_arrays);
|
||||
const auto component_index = it.m_offsets[1 + Is];
|
||||
const auto dst_component_it = dst_component_array.begin() + component_index;
|
||||
|
||||
|
||||
ztu::replace_range(
|
||||
dst_component_array,
|
||||
dst_component_it,
|
||||
dst_component_it + dst_vertex_count,
|
||||
dst_component_it + dst_component_count,
|
||||
src_component_array.begin(),
|
||||
src_component_array.begin() + vertex_count
|
||||
src_component_array.begin() + src_component_count
|
||||
);
|
||||
}, ...);
|
||||
}
|
||||
(std::index_sequence_for<Ts...>{});
|
||||
|
||||
@@ -404,7 +412,7 @@ void assets::detail::generic_mesh_store<z3d::structure<Ts...>>::remove(const ite
|
||||
|
||||
m_component_flag_counts.erase(m_component_flag_counts.begin() + index);
|
||||
|
||||
[&]<auto... Is>(std::index_sequence<Is>)
|
||||
[&]<auto... Is>(std::index_sequence<Is...>)
|
||||
{
|
||||
([&]{
|
||||
if ( component_flags & component_flag_type{ 1 } << Is)
|
||||
@@ -426,9 +434,9 @@ void assets::detail::generic_mesh_store<z3d::structure<Ts...>>::clear()
|
||||
|
||||
m_ids.clear();
|
||||
m_triangles.clear();
|
||||
[&]<auto... Is>(std::index_sequence<Is>)
|
||||
[&]<auto... Is>(std::index_sequence<Is...>)
|
||||
{
|
||||
std::get<Is>(m_component_arrays).clear();
|
||||
(std::get<Is>(m_component_arrays).clear(), ...);
|
||||
} (std::index_sequence_for<Ts...>{});
|
||||
m_component_flag_counts.clear();
|
||||
m_material_ids.clear();
|
||||
|
||||
@@ -198,7 +198,7 @@ assets::detail::generic_point_cloud_store_iterator<Ts...>::dereference(std::inde
|
||||
template<typename... Ts>
|
||||
std::tuple<std::add_pointer_t<Ts>...> assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::component_iterators()
|
||||
{
|
||||
return [&]<auto... Is>(std::index_sequence<Is>)
|
||||
return [&]<auto... Is>(std::index_sequence<Is...>)
|
||||
{
|
||||
return std::make_tuple(std::get<Is>(m_component_arrays).data()...);
|
||||
}
|
||||
@@ -208,7 +208,7 @@ std::tuple<std::add_pointer_t<Ts>...> assets::detail::generic_point_cloud_store<
|
||||
template<typename... Ts>
|
||||
std::tuple<std::add_pointer_t<std::add_const_t<Ts>>...> assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::component_iterators() const
|
||||
{
|
||||
return [&]<auto... Is>(std::index_sequence<Is>)
|
||||
return [&]<auto... Is>(std::index_sequence<Is...>)
|
||||
{
|
||||
return std::make_tuple(std::get<Is>(m_component_arrays).data()...);
|
||||
}
|
||||
@@ -219,7 +219,7 @@ template<typename... Ts>
|
||||
std::array<typename assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::count_type, 1 + sizeof...(Ts)>
|
||||
assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::array_counts() const
|
||||
{
|
||||
return [&]<auto... Is>(std::index_sequence<Is>)
|
||||
return [&]<auto... Is>(std::index_sequence<Is...>)
|
||||
{
|
||||
return std::array{
|
||||
std::get<Is>(m_component_arrays).size()...
|
||||
@@ -268,8 +268,9 @@ bool assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::unsafe_in
|
||||
: std::numeric_limits<count_type>::max()
|
||||
);
|
||||
|
||||
[&]<auto... Is>(std::integer_sequence<Is...>)
|
||||
[&]<auto... Is>(std::index_sequence<Is...>)
|
||||
{
|
||||
([&] {
|
||||
const auto& component_array = std::get<Is>(data.component_arrays);
|
||||
if (not component_array.empty())
|
||||
{
|
||||
@@ -280,6 +281,7 @@ bool assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::unsafe_in
|
||||
vertex_count = component_count;
|
||||
}
|
||||
}
|
||||
}, ...);
|
||||
}
|
||||
(std::index_sequence_for<Ts...>{});
|
||||
|
||||
@@ -305,8 +307,9 @@ bool assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::unsafe_in
|
||||
m_component_flag_counts[index] = src_component_flag_count;
|
||||
}
|
||||
|
||||
[&]<auto... Is>(std::integer_sequence<Is...>)
|
||||
[&]<auto... Is>(std::index_sequence<Is...>)
|
||||
{
|
||||
([&] {
|
||||
const auto is_component_enabled = src_component_flags & component_flag_type{ 1 } << Is;
|
||||
const auto was_component_enabled = (
|
||||
new_entry
|
||||
@@ -326,6 +329,7 @@ bool assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::unsafe_in
|
||||
src_component_array.begin(),
|
||||
src_component_array.begin() + vertex_count
|
||||
);
|
||||
}, ...);
|
||||
}
|
||||
(std::index_sequence_for<Ts...>{});
|
||||
|
||||
@@ -368,7 +372,7 @@ void assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::remove(co
|
||||
|
||||
m_component_flag_counts.erase(m_component_flag_counts.begin() + index);
|
||||
|
||||
[&]<auto... Is>(std::index_sequence<Is>)
|
||||
[&]<auto... Is>(std::index_sequence<Is...>)
|
||||
{
|
||||
([&]{
|
||||
if ( component_flags & component_flag_type{ 1 } << Is)
|
||||
@@ -387,9 +391,9 @@ void assets::detail::generic_point_cloud_store<z3d::structure<Ts...>>::clear()
|
||||
auto lock = std::unique_lock{ m_mutex };
|
||||
|
||||
m_ids.clear();
|
||||
[&]<auto... Is>(std::index_sequence<Is>)
|
||||
[&]<auto... Is>(std::index_sequence<Is...>)
|
||||
{
|
||||
std::get<Is>(m_component_arrays).clear();
|
||||
(std::get<Is>(m_component_arrays).clear(), ...);
|
||||
} (std::index_sequence_for<Ts...>{});
|
||||
m_component_flag_counts.clear();
|
||||
}
|
||||
|
||||
@@ -27,12 +27,12 @@ assets::pose_list_store_iterator<Char>::pose_list_store_iterator(
|
||||
|
||||
template<typename Char>
|
||||
typename assets::pose_list_store_iterator<Char>::reference assets::pose_list_store_iterator<Char>::operator*() const {
|
||||
return dereference(std::index_sequence_for<Char>{});
|
||||
return dereference();
|
||||
}
|
||||
|
||||
template<typename Char>
|
||||
assets::pose_list_store_iterator<Char>& assets::pose_list_store_iterator<Char>::operator++() {
|
||||
adjust_offsets(std::index_sequence_for<Char>{}, 1);
|
||||
calc_offset(1);
|
||||
++m_index;
|
||||
return *this;
|
||||
}
|
||||
@@ -46,7 +46,7 @@ assets::pose_list_store_iterator<Char> assets::pose_list_store_iterator<Char>::o
|
||||
|
||||
template<typename Char>
|
||||
assets::pose_list_store_iterator<Char>& assets::pose_list_store_iterator<Char>::operator--() {
|
||||
adjust_offsets(std::index_sequence_for<Char>{}, -1);
|
||||
calc_offset(-1);
|
||||
--m_index;
|
||||
return *this;
|
||||
}
|
||||
@@ -61,7 +61,7 @@ assets::pose_list_store_iterator<Char> assets::pose_list_store_iterator<Char>::o
|
||||
template<typename Char>
|
||||
assets::pose_list_store_iterator<Char>& assets::pose_list_store_iterator<Char>::operator+=(const difference_type n)
|
||||
{
|
||||
adjust_offsets(std::index_sequence_for<Char>{}, n);
|
||||
calc_offset(n);
|
||||
m_index += n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -30,12 +30,12 @@ assets::shader_source_store_iterator<Char>::shader_source_store_iterator(
|
||||
|
||||
template<typename Char>
|
||||
typename assets::shader_source_store_iterator<Char>::reference assets::shader_source_store_iterator<Char>::operator*() const {
|
||||
return dereference(std::index_sequence_for<Char>{});
|
||||
return dereference();
|
||||
}
|
||||
|
||||
template<typename Char>
|
||||
assets::shader_source_store_iterator<Char>& assets::shader_source_store_iterator<Char>::operator++() {
|
||||
adjust_offsets(std::index_sequence_for<Char>{}, 1);
|
||||
calc_offset(1);
|
||||
++m_index;
|
||||
return *this;
|
||||
}
|
||||
@@ -49,7 +49,7 @@ assets::shader_source_store_iterator<Char> assets::shader_source_store_iterator<
|
||||
|
||||
template<typename Char>
|
||||
assets::shader_source_store_iterator<Char>& assets::shader_source_store_iterator<Char>::operator--() {
|
||||
adjust_offsets(std::index_sequence_for<Char>{}, -1);
|
||||
calc_offset(-1);
|
||||
--m_index;
|
||||
return *this;
|
||||
}
|
||||
@@ -64,7 +64,7 @@ assets::shader_source_store_iterator<Char> assets::shader_source_store_iterator<
|
||||
template<typename Char>
|
||||
assets::shader_source_store_iterator<Char>& assets::shader_source_store_iterator<Char>::operator+=(const difference_type n)
|
||||
{
|
||||
adjust_offsets(std::index_sequence_for<Char>{}, n);
|
||||
calc_offset(n);
|
||||
m_index += n;
|
||||
return *this;
|
||||
}
|
||||
@@ -172,7 +172,7 @@ assets::shader_source_store_iterator<Char>::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::iterator, bool> assets::shader_source_store::find(id_type id)
|
||||
{
|
||||
auto lock = std::shared_lock{ m_mutex };
|
||||
|
||||
return unsafe_find(id);
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
bool assets::shader_source_store::insert(iterator it, const id_type id, const data_type& data)
|
||||
inline std::pair<assets::shader_source_store::const_iterator, bool> assets::shader_source_store::find(id_type id) const
|
||||
{
|
||||
auto lock = std::shared_lock{ m_mutex };
|
||||
|
||||
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::iterator, bool> assets::shader_source_store::find(id_type id)
|
||||
inline std::pair<assets::shader_source_store::iterator, bool> 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_source_store::iterator, bool> assets::shader_sou
|
||||
return { begin() + index, found };
|
||||
}
|
||||
|
||||
inline std::pair<assets::shader_source_store::const_iterator, bool> assets::shader_source_store::find(id_type id) const
|
||||
inline std::pair<assets::shader_source_store::const_iterator, bool> 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()
|
||||
|
||||
@@ -9,6 +9,141 @@
|
||||
#include "glm/gtx/euler_angles.hpp"
|
||||
#include <charconv>
|
||||
#include <fstream>
|
||||
#include <execution>
|
||||
#include <queue>
|
||||
|
||||
|
||||
template<bool Normal, bool Color, bool Reflectance>
|
||||
std::error_code assets::generic_3dtk_loader<Normal, Color, Reflectance>::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<bool Normal, bool Color, bool Reflectance>
|
||||
std::error_code assets::generic_3dtk_loader<Normal, Color, Reflectance>::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<bool Normal, bool Color, bool Reflectance>
|
||||
assets::generic_3dtk_loader<Normal, Color, Reflectance>::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<bool Normal, bool Color, bool Reflectance>
|
||||
void assets::generic_3dtk_loader<Normal, Color, Reflectance>::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<bool Normal, bool Color, bool Reflectance>
|
||||
void assets::generic_3dtk_loader<Normal, Color, Reflectance>::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<bool Normal, bool Color, bool Reflectance>
|
||||
ztu::result<pose_prefetch_lookup::index_type> generic_3dtk_loader<Normal, Color, Reflectance>::parse_index(
|
||||
@@ -37,35 +172,12 @@ ztu::result<pose_prefetch_lookup::index_type> generic_3dtk_loader<Normal, Color,
|
||||
return index;
|
||||
}
|
||||
|
||||
template<bool Normal, bool Color, bool Reflectance>
|
||||
std::error_code generic_3dtk_loader<Normal, Color, Reflectance>::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<bool Normal, bool Color, bool Reflectance>
|
||||
std::error_code generic_3dtk_loader<Normal, Color, Reflectance>::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<Normal, Color, Reflectance>::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<Normal, Color, Reflectance>::load(
|
||||
load_file(filename.data());
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (const auto directory : paths.directories)
|
||||
{
|
||||
directory_buffer.assign(directory.begin(), directory.end());
|
||||
|
||||
@@ -63,58 +63,47 @@ inline std::error_code make_error_code(codes e)
|
||||
}
|
||||
} // namespace mtl_loader_error
|
||||
|
||||
template<int L, typename T>
|
||||
std::errc parse_numeric_vector(std::string_view param, z3d::vec<L, T>& 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<char>(8 * 1024, '\0');
|
||||
|
||||
auto in = std::ifstream{};
|
||||
|
||||
auto path_buffer = fs::path{};
|
||||
auto filename_buffer = fs::path{};
|
||||
|
||||
const auto process_file = [&]()
|
||||
{
|
||||
in.open(filename_buffer);
|
||||
if (not in.is_open()) {
|
||||
ztu::logger::error("Could not open .mtl file '%'", filename_buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
filename_buffer.remove_filename();
|
||||
|
||||
find_textures(buffer, path_buffer, filename_buffer, in, queue.texture.files);
|
||||
|
||||
in.close();
|
||||
};
|
||||
|
||||
// TODO properly extract
|
||||
for (const auto file : paths.files)
|
||||
{
|
||||
filename_buffer.assign(file);
|
||||
process_file();
|
||||
}
|
||||
|
||||
for (const auto directory : paths.directories)
|
||||
{
|
||||
for (const auto& file : fs::directory_iterator{ directory }) {
|
||||
|
||||
filename_buffer.assign(file.path());
|
||||
|
||||
// Avoid heap allocation of .extension()
|
||||
if (not std::string_view(filename_buffer.c_str()).ends_with(".obj"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
process_file();
|
||||
}
|
||||
std::for_each(
|
||||
std::execution::parallel_unsequenced_policy{},
|
||||
m_path_buffer.begin(),
|
||||
m_path_buffer.end(),
|
||||
prefetcher_context{
|
||||
lookups
|
||||
}
|
||||
);
|
||||
|
||||
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<int>(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<char, 2>;
|
||||
|
||||
static constexpr auto postfix_length = std::tuple_size_v<long_postfix_type>;
|
||||
|
||||
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<std::size_t>(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<codes>(
|
||||
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::texture_id> assets::mtl_parser::parser_context::fetch_texture_id(
|
||||
@@ -380,8 +502,8 @@ std::optional<assets::texture_id> 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::texture_id> assets::mtl_parser::parser_context::fetch_text
|
||||
|
||||
return texture_id_it->second;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename T, std::size_t Count>
|
||||
std::errc parse_numeric_vector(std::string_view param, std::array<T, Count>& values)
|
||||
{
|
||||
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<char> 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<char, 2>;
|
||||
|
||||
static constexpr auto postfix_length = std::tuple_size_v<long_postfix_type>;
|
||||
|
||||
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<std::size_t>(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());
|
||||
}
|
||||
|
||||
@@ -1,602 +0,0 @@
|
||||
#include "assets/file_parsers/obj_loader.hpp"
|
||||
|
||||
#include <charconv>
|
||||
#include <fstream>
|
||||
#include <array>
|
||||
|
||||
#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<codes>(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<int>(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<z3d::vertex_index>(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<codes>(
|
||||
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<char> 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<char>(8 * 1024, '\0');
|
||||
|
||||
auto in = std::ifstream{};
|
||||
|
||||
auto path_buffer = fs::path{};
|
||||
auto filename_buffer = fs::path{};
|
||||
|
||||
const auto process_file = [&]()
|
||||
{
|
||||
in.open(filename_buffer);
|
||||
if (not in.is_open()) {
|
||||
ztu::logger::error("Could not open .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<indexed_vertex_type>{};
|
||||
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<typename T, std::size_t Count>
|
||||
std::errc parse_numeric_vector(std::string_view param, std::array<T, Count>& 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 {};
|
||||
};
|
||||
530
source/assets/file_parsers/obj_parser.cpp
Executable file
530
source/assets/file_parsers/obj_parser.cpp
Executable file
@@ -0,0 +1,530 @@
|
||||
#include "assets/file_parsers/obj_parser.hpp"
|
||||
|
||||
#include <charconv>
|
||||
#include <fstream>
|
||||
#include <array>
|
||||
|
||||
#include "assets/components/mesh_vertex_components.hpp"
|
||||
|
||||
#include "util/logger.hpp"
|
||||
#include "util/for_each.hpp"
|
||||
#include "util/line_parser.hpp"
|
||||
#include <execution>
|
||||
|
||||
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<codes>(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<int>(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<int L, typename T>
|
||||
std::errc parse_numeric_vector(std::string_view param, z3d::vec<L, T>& 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<codes>(
|
||||
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<z3d::vertex_index>(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());
|
||||
}
|
||||
@@ -3,159 +3,90 @@
|
||||
#include "util/binary_ifstream.hpp"
|
||||
#include "util/unroll_bool_template.hpp"
|
||||
#include "util/logger.hpp"
|
||||
#include <execution>
|
||||
|
||||
template<bool Normals>
|
||||
std::error_code read_body(
|
||||
binary_ifstream& in,
|
||||
const std::uint32_t expected_triangle_count,
|
||||
std::vector<mesh_vertex_components::position>& positions,
|
||||
std::vector<mesh_vertex_components::normal>& normals,
|
||||
std::vector<std::array<ztu::u32, 3>>& 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 }
|
||||
{
|
||||
for (auto& component : vector)
|
||||
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()
|
||||
{
|
||||
float component32;
|
||||
if (const auto e = in.read_ieee754<std::endian::little>(component32))
|
||||
m_mesh.clear();
|
||||
m_vertex_index_lookup.clear();
|
||||
}
|
||||
|
||||
template<int L>
|
||||
std::error_code read_vector(binary_ifstream& in, z3d::vec<L, float>& vector)
|
||||
{
|
||||
for (int i{}; i != L; ++i)
|
||||
{
|
||||
if (const auto e = in.read_ieee754<std::endian::little>(vector[i))
|
||||
{
|
||||
return e;
|
||||
}
|
||||
component = component32;
|
||||
}
|
||||
return {};
|
||||
};
|
||||
|
||||
for (std::uint32_t i{}; i != expected_triangle_count; ++i) {
|
||||
|
||||
auto normal = mesh_vertex_components::normal{};
|
||||
if constexpr (Normals)
|
||||
void assets::stl_loader::parser_context::operator()(lookup_type::const_pointer entry) noexcept
|
||||
{
|
||||
if (const auto e = read_vector(normal))
|
||||
{
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
auto triangle = std::array<ztu::u32, 3>{};
|
||||
|
||||
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<std::uint16_t>())
|
||||
{
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::error_code stl_loader::read_directory(
|
||||
const std::filesystem::path& path,
|
||||
std::vector<dynamic_mesh_data>& meshes,
|
||||
mesh_vertex_components::flags enabled_mesh_vertex_componentss,
|
||||
std::vector<dynamic_material_data>& 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);
|
||||
}
|
||||
|
||||
for (const auto& file : fs::directory_iterator{ path / "frames" })
|
||||
{
|
||||
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()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
std::error_code stl_loader::read(
|
||||
const std::filesystem::path& filename,
|
||||
std::vector<dynamic_mesh_data>& meshes,
|
||||
mesh_vertex_components::flags enabled_mesh_vertex_componentss,
|
||||
std::vector<dynamic_material_data>&,
|
||||
material_component::flags,
|
||||
ztu::u32,
|
||||
const bool pedantic
|
||||
) {
|
||||
auto error = std::error_code{};
|
||||
const auto& [ filename, id ] = *entry;
|
||||
|
||||
auto in = binary_ifstream{};
|
||||
|
||||
if ((error = in.open(filename, true)))
|
||||
if (const auto e = in.open(filename, true))
|
||||
{
|
||||
return error;
|
||||
ztu::logger::error("Cannot open stl file %.", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
reset();
|
||||
|
||||
auto header_bytes_left = static_cast<binary_ifstream::size_type>(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<binary_ifstream::char_type, ascii_magic_string.size()>{};
|
||||
|
||||
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<std::endian::little>(expected_triangle_count)))
|
||||
if (const auto e = in.read<std::endian::little>(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);
|
||||
|
||||
const auto normals_enabled = (
|
||||
(enabled_mesh_vertex_componentss & mesh_vertex_components::flags::normal) != mesh_vertex_components::flags::none
|
||||
);
|
||||
|
||||
error = unroll_bool_function_template([&]<bool Normals>() {
|
||||
return read_body<Normals>(
|
||||
in,expected_triangle_count,
|
||||
positions,
|
||||
normals,
|
||||
triangles
|
||||
);
|
||||
}, normals_enabled);
|
||||
|
||||
// Free any unused reserved memory
|
||||
positions.shrink_to_fit();
|
||||
normals.shrink_to_fit();
|
||||
triangles.shrink_to_fit();
|
||||
|
||||
if (error)
|
||||
mesh_vertex_components::normal normal;
|
||||
if (((vertex_parsing_error = read_vector(in, normal))))
|
||||
{
|
||||
return error;
|
||||
break;
|
||||
}
|
||||
|
||||
ztu::logger::debug("Normal count: %", normals.size());
|
||||
auto triangle = z3d::index_triangle{};
|
||||
|
||||
if (not positions.empty())
|
||||
for (auto& index : triangle)
|
||||
{
|
||||
mesh.components() |= mesh_vertex_components::flags::position;
|
||||
}
|
||||
|
||||
if (not normals.empty())
|
||||
mesh_vertex_components::position position;
|
||||
if (((vertex_parsing_error = read_vector(in, normal))))
|
||||
{
|
||||
ztu::logger::debug("Enabling normals!!!");
|
||||
mesh.components() |= mesh_vertex_components::flags::normal;
|
||||
break;
|
||||
}
|
||||
|
||||
meshes.emplace_back(std::move(mesh));
|
||||
|
||||
return {};
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
m_mesh.triangles().emplace_back(triangle);
|
||||
|
||||
// Skip attribute bytes
|
||||
if (((vertex_parsing_error = in.skip<std::uint16_t>())))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (vertex_parsing_error)
|
||||
{
|
||||
ztu::logger::error("Error while parsing stl vertices in %: %", filename, vertex_parsing_error.message());
|
||||
return;
|
||||
}
|
||||
|
||||
m_mesh.component_flags |= mesh_vertex_components::flags::position;
|
||||
m_mesh.component_flags |= mesh_vertex_components::flags::normal;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user