diff --git a/CMakeLists.txt b/CMakeLists.txt index b38111ff..f6206454 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,8 +18,10 @@ endif() #### CGoGN PATH set(CGOGN_PATH "${CMAKE_CURRENT_SOURCE_DIR}") + #### Here are located the FindPackages that we need list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules") +list(APPEND CMAKE_PREFIX_PATH "${CMAKE_BINARY_DIR}") #### Compile Options include(cmake/CompilerOptions.cmake) @@ -30,7 +32,7 @@ include(cmake/EnableCoverageReport.cmake) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) -set(CGOGN_SOURCE_DIR ${CGOGN_PATH}/cgogn) +set(CGOGN_SOURCE_DIR ${CGOGN_PATH}) ### External Templates option(CGOGN_EXTERNAL_TEMPLATES "Use external templates to reduce compile time" OFF) @@ -43,8 +45,10 @@ set(CGOGN_THIRDPARTY_DIR ${CGOGN_PATH}/thirdparty) option(CGOGN_PROVIDE_EIGEN "Use the version of eigen that is packaged with CGoGN." ON) option(CGOGN_PROVIDE_TINYXML2 "Use the version of tinyxml2 that is packaged with CGoGN." ON) option(CGOGN_BUILD_TESTS "Build cgogn unit tests using google test framework." ON) +option(CGOGN_BUILD_EXAMPLES "Build some example apps." ON) option(CGOGN_BUILD_BENCHS "Build the benchmarks using google benchmark framework." ON) option(CGOGN_USE_OPENMP "Activate openMP directives." OFF) +option(CGOGN_ENABLE_LTO "Enable link-time optimizations (only with gcc)" ON) if (NOT MSVC) option(CGOGN_USE_GLIBCXX_DEBUG "Use the debug version of STL (useful for bounds checking)." OFF) option(CGOGN_USE_GLIBCXX_DEBUG_PEDANTIC "Use an extremely picky debug version of STL." OFF) @@ -125,14 +129,44 @@ else() add_definitions("-DCGOGN_ENDIANNESS=CGOGN_LITTLE_ENDIAN") endif() +#### Link time optimisation +if (CGOGN_ENABLE_LTO AND ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") AND (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")) + add_flags(CMAKE_CXX_FLAGS_RELEASE -flto) + find_program(GCC_AR gcc-ar) + if (GCC_AR) + set(CMAKE_AR ${GCC_AR}) + endif() + find_program(GCC_RANLIB gcc-ranlib) + if (GCC_RANLIB) + set(CMAKE_RANLIB ${GCC_RANLIB}) + endif() +endif() + +include(GenerateExportHeader) +include(CMakePackageConfigHelpers) add_subdirectory(${CGOGN_THIRDPARTY_DIR}) -add_subdirectory(${CGOGN_SOURCE_DIR}) +add_subdirectory(${CGOGN_SOURCE_DIR}/cgogn) if(${CGOGN_BUILD_BENCHS}) add_subdirectory(benchmarks) endif(${CGOGN_BUILD_BENCHS}) +if(CGOGN_BUILD_TESTS) + add_subdirectory(cgogn/core/tests) + add_subdirectory(cgogn/geometry/tests) + add_subdirectory(cgogn/modeling/tests) +endif() + +if(CGOGN_BUILD_EXAMPLES) + add_subdirectory(cgogn/core/examples) + add_subdirectory(cgogn/geometry/examples) + add_subdirectory(cgogn/io/examples) + add_subdirectory(cgogn/io/mesh_generation/examples) + add_subdirectory(cgogn/modeling/examples) + add_subdirectory(cgogn/rendering/examples) +endif() + ## TODO a mettre dans un fichier cmake particulier diff --git a/benchmarks/multithreading/bench_multithreading.cpp b/benchmarks/multithreading/bench_multithreading.cpp index 7ae51f4e..c6c6fcf2 100644 --- a/benchmarks/multithreading/bench_multithreading.cpp +++ b/benchmarks/multithreading/bench_multithreading.cpp @@ -24,10 +24,10 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include @@ -51,9 +51,9 @@ const uint32 ITERATIONS = 1u; using Vec3 = cgogn::geometry::Vec_T>; template -using VertexAttributeHandler = Map2::VertexAttributeHandler; +using VertexAttribute = Map2::VertexAttribute; template -using FaceAttributeHandler = Map2::FaceAttributeHandler; +using FaceAttribute = Map2::FaceAttribute; static void BENCH_Dart_count_single_threaded(benchmark::State& state) { @@ -90,9 +90,9 @@ static void BENCH_faces_normals_single_threaded(benchmark::State& state) while(state.KeepRunning()) { state.PauseTiming(); - VertexAttributeHandler vertex_position = bench_map.get_attribute("position"); + VertexAttribute vertex_position = bench_map.get_attribute("position"); cgogn_assert(vertex_position.is_valid()); - FaceAttributeHandler face_normal = bench_map.get_attribute("normal"); + FaceAttribute face_normal = bench_map.get_attribute("normal"); cgogn_assert(face_normal.is_valid()); state.ResumeTiming(); @@ -108,18 +108,20 @@ static void BENCH_faces_normals_cache_single_threaded(benchmark::State& state) while(state.KeepRunning()) { state.PauseTiming(); - VertexAttributeHandler vertex_position = bench_map.get_attribute("position"); + VertexAttribute vertex_position = bench_map.get_attribute("position"); cgogn_assert(vertex_position.is_valid()); - FaceAttributeHandler face_normal = bench_map.get_attribute("normal"); + FaceAttribute face_normal = bench_map.get_attribute("normal"); cgogn_assert(face_normal.is_valid()); - cgogn::CellCache cache(bench_map); + cgogn::CellCache cache(bench_map); + cache.template build(); state.ResumeTiming(); bench_map.foreach_cell([&] (Face f) { face_normal[f] = cgogn::geometry::face_normal(bench_map, f, vertex_position); - }, cache); + }, + cache); } } @@ -129,9 +131,9 @@ static void BENCH_faces_normals_multi_threaded(benchmark::State& state) while(state.KeepRunning()) { state.PauseTiming(); - VertexAttributeHandler vertex_position = bench_map.get_attribute("position"); + VertexAttribute vertex_position = bench_map.get_attribute("position"); cgogn_assert(vertex_position.is_valid()); - FaceAttributeHandler face_normal_mt = bench_map.get_attribute("normal_mt"); + FaceAttribute face_normal_mt = bench_map.get_attribute("normal_mt"); cgogn_assert(face_normal_mt.is_valid()); state.ResumeTiming(); @@ -143,7 +145,7 @@ static void BENCH_faces_normals_multi_threaded(benchmark::State& state) { state.PauseTiming(); - FaceAttributeHandler face_normal = bench_map.get_attribute("normal"); + FaceAttribute face_normal = bench_map.get_attribute("normal"); bench_map.template foreach_cell([&] (Face f) { Vec3 error = face_normal[f] - face_normal_mt[f]; @@ -157,7 +159,6 @@ static void BENCH_faces_normals_multi_threaded(benchmark::State& state) }); state.ResumeTiming(); } - } } @@ -166,18 +167,20 @@ static void BENCH_faces_normals_cache_multi_threaded(benchmark::State& state) while(state.KeepRunning()) { state.PauseTiming(); - VertexAttributeHandler vertex_position = bench_map.get_attribute("position"); + VertexAttribute vertex_position = bench_map.get_attribute("position"); cgogn_assert(vertex_position.is_valid()); - FaceAttributeHandler face_normal = bench_map.get_attribute("normal"); + FaceAttribute face_normal = bench_map.get_attribute("normal"); cgogn_assert(face_normal.is_valid()); - cgogn::CellCache cache(bench_map); + cgogn::CellCache cache(bench_map); + cache.template build(); state.ResumeTiming(); bench_map.parallel_foreach_cell([&] (Face f, uint32) { face_normal[f] = cgogn::geometry::face_normal(bench_map, f, vertex_position); - }, cache); + }, + cache); } } @@ -188,9 +191,9 @@ static void BENCH_vertices_normals_single_threaded(benchmark::State& state) while(state.KeepRunning()) { state.PauseTiming(); - VertexAttributeHandler vertex_position = bench_map.get_attribute("position"); + VertexAttribute vertex_position = bench_map.get_attribute("position"); cgogn_assert(vertex_position.is_valid()); - VertexAttributeHandler vertices_normal = bench_map.get_attribute("normal"); + VertexAttribute vertices_normal = bench_map.get_attribute("normal"); cgogn_assert(vertices_normal.is_valid()); state.ResumeTiming(); @@ -206,18 +209,20 @@ static void BENCH_vertices_normals_cache_single_threaded(benchmark::State& state while(state.KeepRunning()) { state.PauseTiming(); - VertexAttributeHandler vertex_position = bench_map.get_attribute("position"); + VertexAttribute vertex_position = bench_map.get_attribute("position"); cgogn_assert(vertex_position.is_valid()); - VertexAttributeHandler vertices_normal = bench_map.get_attribute("normal"); + VertexAttribute vertices_normal = bench_map.get_attribute("normal"); cgogn_assert(vertices_normal.is_valid()); - cgogn::CellCache cache(bench_map); + cgogn::CellCache cache(bench_map); + cache.template build(); state.ResumeTiming(); bench_map.foreach_cell([&] (Vertex v) { vertices_normal[v] = cgogn::geometry::vertex_normal(bench_map, v, vertex_position); - }, cache); + }, + cache); } } @@ -227,9 +232,9 @@ static void BENCH_vertices_normals_multi_threaded(benchmark::State& state) while(state.KeepRunning()) { state.PauseTiming(); - VertexAttributeHandler vertex_position = bench_map.get_attribute("position"); + VertexAttribute vertex_position = bench_map.get_attribute("position"); cgogn_assert(vertex_position.is_valid()); - VertexAttributeHandler vertices_normal_mt = bench_map.get_attribute("normal_mt"); + VertexAttribute vertices_normal_mt = bench_map.get_attribute("normal_mt"); cgogn_assert(vertices_normal_mt.is_valid()); state.ResumeTiming(); @@ -241,7 +246,7 @@ static void BENCH_vertices_normals_multi_threaded(benchmark::State& state) { state.PauseTiming(); - VertexAttributeHandler vertices_normal = bench_map.get_attribute("normal"); + VertexAttribute vertices_normal = bench_map.get_attribute("normal"); bench_map.template foreach_cell([&] (Vertex v) { Vec3 error = vertices_normal[v] - vertices_normal_mt[v]; @@ -263,18 +268,20 @@ static void BENCH_vertices_normals_cache_multi_threaded(benchmark::State& state) while(state.KeepRunning()) { state.PauseTiming(); - VertexAttributeHandler vertex_position = bench_map.get_attribute("position"); + VertexAttribute vertex_position = bench_map.get_attribute("position"); cgogn_assert(vertex_position.is_valid()); - VertexAttributeHandler vertices_normal = bench_map.get_attribute("normal"); + VertexAttribute vertices_normal = bench_map.get_attribute("normal"); cgogn_assert(vertices_normal.is_valid()); - cgogn::CellCache cache(bench_map); + cgogn::CellCache cache(bench_map); + cache.template build(); state.ResumeTiming(); bench_map.parallel_foreach_cell([&] (Vertex v, uint32) { vertices_normal[v] = cgogn::geometry::vertex_normal(bench_map, v, vertex_position); - }, cache); + }, + cache); } } diff --git a/cgogn/CMakeLists.txt b/cgogn/CMakeLists.txt index eaaf0807..dad72607 100644 --- a/cgogn/CMakeLists.txt +++ b/cgogn/CMakeLists.txt @@ -1,6 +1,6 @@ add_subdirectory(core) -add_subdirectory(io) add_subdirectory(geometry) +add_subdirectory(io) add_subdirectory(modeling) if(CGOGN_USE_QT) diff --git a/cgogn/core/CMakeLists.txt b/cgogn/core/CMakeLists.txt index 249014d2..9d6abd88 100644 --- a/cgogn/core/CMakeLists.txt +++ b/cgogn/core/CMakeLists.txt @@ -19,7 +19,7 @@ set(HEADER_FILES cmap/cmap2_builder.h cmap/cmap3.h cmap/cmap3_builder.h - cmap/attribute_handler.h + cmap/attribute.h container/chunk_array_container.h container/chunk_array_factory.h @@ -36,14 +36,14 @@ set(HEADER_FILES utils/serialization.h utils/thread.h utils/thread_pool.h - utils/thread_barrier.h utils/string.h - utils/precision.h utils/masks.h utils/logger.h utils/log_entry.h utils/logger_output.h utils/log_stream.h + utils/numerics.h + utils/type_traits.h ) set(SOURCE_FILES @@ -76,13 +76,39 @@ set(SOURCE_FILES ) add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) +# generate_export_header(${PROJECT_NAME} +# EXPORT_MACRO_NAME "CGOGN_CORE_API" +# EXPORT_FILE_NAME "${CMAKE_BINARY_DIR}/exports/${PROJECT_NAME}_export.h" +# ) -# use of target_compile_options to have a transitive c++11 flag +# use of target_compile_options to have transitive flags if(NOT MSVC) target_compile_options(${PROJECT_NAME} PUBLIC "-std=c++11") + remove_flags(CMAKE_CXX_FLAGS "-std=c++11") + if(${CGOGN_USE_CXX11_ABI}) + target_compile_options(${PROJECT_NAME} PUBLIC "-D_GLIBCXX_USE_CXX11_ABI") + remove_flags(CMAKE_CXX_FLAGS "-D_GLIBCXX_USE_CXX11_ABI") + endif() + if (${CGOGN_USE_GLIBCXX_DEBUG}) + target_compile_options(${PROJECT_NAME} PUBLIC "-D_GLIBCXX_DEBUG") + remove_flags(CMAKE_CXX_FLAGS "-D_GLIBCXX_DEBUG") + if(${CGOGN_USE_GLIBCXX_DEBUG_PEDANTIC}) + target_compile_options(${PROJECT_NAME} PUBLIC "-D_GLIBCXX_DEBUG_PEDANTIC") + remove_flags(CMAKE_CXX_FLAGS "-D_GLIBCXX_DEBUG_PEDANTIC") + endif() + endif() + if(${CGOGN_USE_PARALLEL_GLIBCXX} AND (NOT ${CGOGN_USE_GLIBCXX_DEBUG})) + target_compile_options(${PROJECT_NAME} PUBLIC "-D_GLIBCXX_PARALLEL") + remove_flags(CMAKE_CXX_FLAGS "-D_GLIBCXX_PARALLEL") + endif() endif() + if(MSVC) target_compile_options(${PROJECT_NAME} PUBLIC "-D_USE_MATH_DEFINES") + ## CGOGN_WIN_VER : has value 61 for windows 7, 62 for windows 8, 63 for windows 8.1, 100 for windows 10 + set(WIN_VERSION "") + string(REPLACE "." "" WIN_VERSION ${CMAKE_SYSTEM_VERSION}) + target_compile_options(${PROJECT_NAME} PUBLIC "-DCGOGN_WIN_VER=${WIN_VERSION}") endif() set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "_d") @@ -90,23 +116,13 @@ set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "_d") target_include_directories(${PROJECT_NAME} PUBLIC $ $ - $ + $ ) - install(DIRECTORY basic cmap container utils - DESTINATION include/cgogn/core/ +install(FILES "dll.h" DESTINATION "include/cgogn/core/") +install(DIRECTORY basic cmap container utils + DESTINATION "include/cgogn/core/" FILES_MATCHING PATTERN "*.h" - ) - - install(TARGETS ${PROJECT_NAME} - EXPORT ${PROJECT_NAME}Targets - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib - ) - -add_subdirectory(examples) +) -if(CGOGN_BUILD_TESTS) - add_subdirectory(tests) -endif() +cgogn_create_package("${CGOGN_SOURCE_DIR};${CGOGN_THIRDPARTY_TERMCOLOR_INCLUDE_DIR}" "include") diff --git a/cgogn/core/basic/cell.h b/cgogn/core/basic/cell.h index 751d5644..8c25d36e 100644 --- a/cgogn/core/basic/cell.h +++ b/cgogn/core/basic/cell.h @@ -21,13 +21,13 @@ * * *******************************************************************************/ -#ifndef CORE_BASIC_CELL_H_ -#define CORE_BASIC_CELL_H_ +#ifndef CGOGN_CORE_BASIC_CELL_H_ +#define CGOGN_CORE_BASIC_CELL_H_ -#include +#include -#include -#include +#include +#include #include @@ -35,6 +35,7 @@ * \file core/basic/cell.h * \brief Orbit and cell definitions used in cgogn. */ + namespace cgogn { @@ -48,11 +49,10 @@ enum Orbit: uint32 PHI2_PHI3, PHI21, PHI21_PHI31, + PHI1_PHI2_PHI3 }; -static const std::size_t NB_ORBITS = Orbit::PHI21_PHI31 + 1; - -static const uint32 EMBNULL = UINT_MAX; +static const std::size_t NB_ORBITS = Orbit::PHI1_PHI2_PHI3 + 1; inline std::string orbit_name(Orbit orbit) { @@ -66,6 +66,7 @@ inline std::string orbit_name(Orbit orbit) case Orbit::PHI2_PHI3: return "cgogn::Orbit::PHI2_PHI3"; break; case Orbit::PHI21: return "cgogn::Orbit::PHI21"; break; case Orbit::PHI21_PHI31: return "cgogn::Orbit::PHI21_PHI31"; break; + case Orbit::PHI1_PHI2_PHI3: return "cgogn::Orbit::PHI1_PHI2_PHI3"; break; // default: cgogn_assert_not_reached("This orbit does not exist"); return "UNKNOWN"; break; } cgogn_assert_not_reached("This orbit does not exist"); @@ -115,7 +116,6 @@ class Cell //TODO // Cell(Cell&& ) = delete; - /** * \brief Tests the validity of the cell. * \retval true if the cell is valid @@ -154,4 +154,4 @@ class Cell } // namespace cgogn -#endif // CORE_BASIC_CELL_H_ +#endif // CGOGN_CORE_BASIC_CELL_H_ diff --git a/cgogn/core/basic/cell_marker.h b/cgogn/core/basic/cell_marker.h index d0597354..9ef6d10d 100644 --- a/cgogn/core/basic/cell_marker.h +++ b/cgogn/core/basic/cell_marker.h @@ -21,11 +21,11 @@ * * *******************************************************************************/ -#ifndef CORE_BASIC_CELL_MARKER_H_ -#define CORE_BASIC_CELL_MARKER_H_ +#ifndef CGOGN_CORE_BASIC_CELL_MARKER_H_ +#define CGOGN_CORE_BASIC_CELL_MARKER_H_ -#include -#include +#include +#include #include namespace cgogn @@ -38,10 +38,9 @@ class CellMarker_T public: - static const uint32 CHUNKSIZE = MAP::CHUNKSIZE; using Self = CellMarker_T; using Map = MAP; - using ChunkArrayBool = ChunkArray; + using ChunkArrayBool = typename Map::ChunkArrayBool; protected: @@ -50,6 +49,8 @@ class CellMarker_T public: + CGOGN_NOT_COPYABLE_NOR_MOVABLE(CellMarker_T); + CellMarker_T(Map& map) : map_(map) { @@ -68,11 +69,6 @@ class CellMarker_T map_.template release_mark_attribute(mark_attribute_); } - CellMarker_T(const Self& dm) = delete; - CellMarker_T(Self&& dm) = delete; - Self& operator=(const Self& dm) = delete; - Self& operator=(Self&& dm) = delete; - inline void mark(Cell c) { cgogn_message_assert(mark_attribute_ != nullptr, "CellMarker has null mark attribute"); @@ -101,11 +97,13 @@ class CellMarker : public CellMarker_T using Self = CellMarker< MAP, ORBIT >; using Map = typename Inherit::Map; - CellMarker(Map& map) : + CGOGN_NOT_COPYABLE_NOR_MOVABLE(CellMarker); + + inline CellMarker(Map& map) : Inherit(map) {} - CellMarker(const MAP& map) : + inline CellMarker(const MAP& map) : Inherit(map) {} @@ -114,11 +112,6 @@ class CellMarker : public CellMarker_T unmark_all(); } - CellMarker(const Self& dm) = delete; - CellMarker(Self&& dm) = delete; - CellMarker& operator=(Self&& dm) = delete; - CellMarker& operator=(const Self& dm) = delete; - inline void unmark_all() { cgogn_message_assert(this->mark_attribute_ != nullptr, "CellMarker has null mark attribute"); @@ -141,7 +134,9 @@ class CellMarkerStore : public CellMarker_T public: - CellMarkerStore(const MAP& map) : + CGOGN_NOT_COPYABLE_NOR_MOVABLE(CellMarkerStore); + + inline CellMarkerStore(const MAP& map) : Inherit(map) { marked_cells_ = cgogn::get_uint_buffers()->get_buffer(); @@ -153,11 +148,6 @@ class CellMarkerStore : public CellMarker_T cgogn::get_uint_buffers()->release_buffer(marked_cells_); } - CellMarkerStore(const Self& dm) = delete; - CellMarkerStore(Self&& dm) = delete; - CellMarkerStore& operator=(Self&& dm) = delete; - CellMarkerStore& operator=(const Self& dm) = delete; - inline void mark(Cell c) { cgogn_message_assert(this->mark_attribute_ != nullptr, "CellMarkerStore has null mark attribute"); @@ -173,12 +163,12 @@ class CellMarkerStore : public CellMarker_T marked_cells_->clear(); } - inline const std::vector* get_marked_cells() const + inline const std::vector& get_marked_cells() const { - return marked_cells_; + return *marked_cells_; } }; } // namespace cgogn -#endif // CORE_BASIC_CELL_MARKER_H_ +#endif // CGOGN_CORE_BASIC_CELL_MARKER_H_ diff --git a/cgogn/core/basic/dart.h b/cgogn/core/basic/dart.h index e94d2195..5d194466 100644 --- a/cgogn/core/basic/dart.h +++ b/cgogn/core/basic/dart.h @@ -21,29 +21,31 @@ * * *******************************************************************************/ -#ifndef CORE_BASIC_DART_H_ -#define CORE_BASIC_DART_H_ +#ifndef CGOGN_CORE_BASIC_DART_H_ +#define CGOGN_CORE_BASIC_DART_H_ #include #include #include -#include + +#include /** * \file cgogn/core/basic/dart.h * \brief Dart definition. */ + namespace cgogn { +// MSVC doesn't support std::numeric_limits::max() when declaring static const variables +static const uint32 INVALID_INDEX = UINT_MAX; + /** * \brief Dart. */ struct Dart { - // MSVC doesn't support std::numeric_limits::max() when declaring static const variables - static const uint32 INVALID_INDEX = UINT_MAX; - /** * \brief the value of a dart. */ @@ -137,4 +139,4 @@ struct Dart } // namespace cgogn -#endif // CORE_BASIC_DART_H_ +#endif // CGOGN_CORE_BASIC_DART_H_ diff --git a/cgogn/core/basic/dart_marker.cpp b/cgogn/core/basic/dart_marker.cpp index dc96491a..a9ad20d1 100644 --- a/cgogn/core/basic/dart_marker.cpp +++ b/cgogn/core/basic/dart_marker.cpp @@ -23,7 +23,7 @@ #define CGOGN_CORE_DLL_EXPORT -#include +#include namespace cgogn { diff --git a/cgogn/core/basic/dart_marker.h b/cgogn/core/basic/dart_marker.h index a4230e67..e81d0e53 100644 --- a/cgogn/core/basic/dart_marker.h +++ b/cgogn/core/basic/dart_marker.h @@ -21,13 +21,13 @@ * * *******************************************************************************/ -#ifndef CORE_BASIC_DART_MARKER_H_ -#define CORE_BASIC_DART_MARKER_H_ +#ifndef CGOGN_CORE_BASIC_DART_MARKER_H_ +#define CGOGN_CORE_BASIC_DART_MARKER_H_ -#include +#include -#include -#include +#include +#include namespace cgogn { @@ -39,7 +39,7 @@ class DartMarker_T using Self = DartMarker_T; using Map = MAP; - using ChunkArrayBool = typename Map::template ChunkArray; + using ChunkArrayBool = typename Map::ChunkArrayBool; protected: @@ -209,4 +209,4 @@ class DartMarkerNoUnmark : public DartMarker_T } // namespace cgogn -#endif // CORE_BASIC_DART_MARKER_H_ +#endif // CGOGN_CORE_BASIC_DART_MARKER_H_ diff --git a/cgogn/core/cmap/attribute_handler.h b/cgogn/core/cmap/attribute.h similarity index 73% rename from cgogn/core/cmap/attribute_handler.h rename to cgogn/core/cmap/attribute.h index 2bdb2247..83e7824b 100644 --- a/cgogn/core/cmap/attribute_handler.h +++ b/cgogn/core/cmap/attribute.h @@ -21,34 +21,37 @@ * * *******************************************************************************/ -#ifndef CORE_MAP_ATTRIBUTE_HANDLER_H_ -#define CORE_MAP_ATTRIBUTE_HANDLER_H_ +#ifndef CGOGN_CORE_MAP_ATTRIBUTE_H_ +#define CGOGN_CORE_MAP_ATTRIBUTE_H_ + +#include +#include +#include +#include +#include +#include -#include -#include -#include namespace cgogn { /** - * \brief Generic AttributeHandler class + * \brief Generic Attribute class * @TPARAM DATA_TRAITS storage traits (for MapBaseData ptr type) */ template -class AttributeHandlerGen +class AttributeGen { public: - - using Self = AttributeHandlerGen; + using Self = AttributeGen; using MapData = MapBaseData; - + using ChunkArrayGen = cgogn::ChunkArrayGen; protected: MapData* map_; public: - inline AttributeHandlerGen(MapData* const map) : + inline AttributeGen(MapData* const map) : map_(map) {} @@ -56,7 +59,7 @@ class AttributeHandlerGen * \brief copy constructor * @param atthg */ - inline AttributeHandlerGen(const Self& atthg) : + inline AttributeGen(const Self& atthg) : map_(atthg.map_) {} @@ -64,7 +67,7 @@ class AttributeHandlerGen * \brief move constructor * @param atthg */ - inline AttributeHandlerGen(Self&& atthg) CGOGN_NOEXCEPT : + inline AttributeGen(Self&& atthg) CGOGN_NOEXCEPT : map_(atthg.map_) { atthg.map_ = nullptr; @@ -75,7 +78,7 @@ class AttributeHandlerGen * @param atthg * @return */ - inline AttributeHandlerGen& operator=(const Self& atthg) + inline AttributeGen& operator=(const Self& atthg) { this->map_ = atthg.map_; return *this; @@ -86,35 +89,41 @@ class AttributeHandlerGen * @param atthg * @return */ - inline AttributeHandlerGen& operator=(Self&& atthg) + inline AttributeGen& operator=(Self&& atthg) CGOGN_NOEXCEPT { this->map_ = atthg.map_; return *this; } - virtual ~AttributeHandlerGen() + virtual ~AttributeGen() {} - virtual bool is_valid() const = 0; + inline bool is_linked_to(MapData* m) const + { + return m == map_; + } - virtual Orbit get_orbit() const = 0; + virtual const std::string& get_name() const = 0; + virtual const std::string& get_type_name() const = 0; + virtual bool is_valid() const = 0; + virtual Orbit get_orbit() const = 0; }; /** - * \brief Generic AttributeHandler class with orbit parameter + * \brief Generic Attribute class with orbit parameter * @TPARAM ORBIT the orbit of the attribute to handlde */ template -class AttributeHandlerOrbit : public AttributeHandlerGen +class AttributeOrbit : public AttributeGen { public: - using Inherit = AttributeHandlerGen; - using Self = AttributeHandlerOrbit; + using Inherit = AttributeGen; + using Self = AttributeOrbit; using MapData = typename Inherit::MapData; - static const uint32 CHUNKSIZE = MapData::CHUNKSIZE; + static const uint32 CHUNKSIZE = DATA_TRAITS::CHUNK_SIZE; static const Orbit orbit_value = ORBIT; template @@ -128,7 +137,7 @@ class AttributeHandlerOrbit : public AttributeHandlerGen public: - inline AttributeHandlerOrbit(MapData* const map) : + inline AttributeOrbit(MapData* const map) : Inherit(map), chunk_array_cont_(nullptr) { @@ -140,7 +149,7 @@ class AttributeHandlerOrbit : public AttributeHandlerGen * \brief copy constructor * @param attho */ - inline AttributeHandlerOrbit(const Self& attho) : + inline AttributeOrbit(const Self& attho) : Inherit(attho), chunk_array_cont_(attho.chunk_array_cont_) {} @@ -149,7 +158,7 @@ class AttributeHandlerOrbit : public AttributeHandlerGen * \brief move constructor * @param attho */ - inline AttributeHandlerOrbit(Self&& attho) CGOGN_NOEXCEPT : + inline AttributeOrbit(Self&& attho) CGOGN_NOEXCEPT : Inherit(std::move(attho)), chunk_array_cont_(attho.chunk_array_cont_) {} @@ -159,7 +168,7 @@ class AttributeHandlerOrbit : public AttributeHandlerGen * @param attho * @return */ - inline AttributeHandlerOrbit& operator=(const Self& attho) + inline AttributeOrbit& operator=(const Self& attho) { Inherit::operator=(attho); chunk_array_cont_ = attho.chunk_array_cont_; @@ -170,7 +179,7 @@ class AttributeHandlerOrbit : public AttributeHandlerGen * @param attho * @return */ - inline AttributeHandlerOrbit& operator=(Self&& attho) + inline AttributeOrbit& operator=(Self&& attho) { Inherit::operator=(std::move(attho)); chunk_array_cont_ = attho.chunk_array_cont_; @@ -182,24 +191,25 @@ class AttributeHandlerOrbit : public AttributeHandlerGen return ORBIT; } - virtual ~AttributeHandlerOrbit() override + virtual ~AttributeOrbit() override {} }; /** - * \brief AttributeHandler class + * \brief Attribute class * @TPARAM T the data type of the attribute to handlde */ template -class AttributeHandler : public AttributeHandlerOrbit +class Attribute : public AttributeOrbit { public: - using Inherit = AttributeHandlerOrbit; - using Self = AttributeHandler; - using value_type = T; - using MapData = typename Inherit::MapData; + using Inherit = AttributeOrbit; + using Self = Attribute; + using value_type = T; + using MapData = typename Inherit::MapData; using TChunkArray = typename Inherit::template ChunkArray; + using ChunkArrayGen = typename Inherit::ChunkArrayGen; protected: @@ -210,9 +220,9 @@ class AttributeHandler : public AttributeHandlerOrbit /** * \brief Default constructor * - * Construct a non-valid AttributeHandler (i.e. not linked to any attribute) + * Construct a non-valid Attribute (i.e. not linked to any attribute) */ - AttributeHandler() : + Attribute() : Inherit(nullptr), chunk_array_(nullptr) {} @@ -220,9 +230,9 @@ class AttributeHandler : public AttributeHandlerOrbit /** * \brief Constructor * @param m the map the attribute belongs to - * @param ca ChunkArray pointer + * @param ca TChunkArray pointer */ - AttributeHandler(MapData* const m, TChunkArray* const ca) : + Attribute(MapData* const m, TChunkArray* const ca) : Inherit(m), chunk_array_(ca) { @@ -238,7 +248,7 @@ class AttributeHandler : public AttributeHandlerOrbit * \brief Copy constructor * @param att */ - AttributeHandler(const Self& att) : + Attribute(const Self& att) : Inherit(att), chunk_array_(att.chunk_array_) { @@ -254,7 +264,7 @@ class AttributeHandler : public AttributeHandlerOrbit * \brief Move constructor * @param att */ - AttributeHandler(Self&& att) CGOGN_NOEXCEPT : + Attribute(Self&& att) CGOGN_NOEXCEPT : Inherit(std::move(att)), chunk_array_(att.chunk_array_) { @@ -271,7 +281,7 @@ class AttributeHandler : public AttributeHandlerOrbit * @param att * @return */ - AttributeHandler& operator=(const Self& att) + Attribute& operator=(const Self& att) { Inherit::operator=(att); @@ -299,7 +309,7 @@ class AttributeHandler : public AttributeHandlerOrbit * @param att * @return */ - AttributeHandler& operator=(Self&& att) + Attribute& operator=(Self&& att) { Inherit::operator=(std::move(att)); @@ -322,7 +332,7 @@ class AttributeHandler : public AttributeHandlerOrbit return *this; } - virtual ~AttributeHandler() override + virtual ~Attribute() override { if (is_valid()) { @@ -332,6 +342,11 @@ class AttributeHandler : public AttributeHandlerOrbit } } + virtual const std::string& get_name() const override + { + return chunk_array_->get_name(); + } + virtual bool is_valid() const override { return chunk_array_ != nullptr; @@ -362,7 +377,7 @@ class AttributeHandler : public AttributeHandlerOrbit */ inline T& operator[](Cell c) { - cgogn_message_assert(is_valid(), "Invalid AttributeHandler"); + cgogn_message_assert(is_valid(), "Invalid Attribute"); return chunk_array_->operator[](this->map_->get_embedding(c)); } @@ -373,10 +388,20 @@ class AttributeHandler : public AttributeHandlerOrbit */ inline const T& operator[](Cell c) const { - cgogn_message_assert(is_valid(), "Invalid AttributeHandler"); + cgogn_message_assert(is_valid(), "Invalid Attribute"); return chunk_array_->operator[](this->map_->get_embedding(c)); } + /** + * @brief set_value method to write in boolean Attributes + * @param c + * @param t + */ + inline void set_value(Cell c, const T& t) + { + chunk_array_->set_value(this->map_->get_embedding(c), t); + } + /** * \brief operator [] * @param i @@ -384,7 +409,7 @@ class AttributeHandler : public AttributeHandlerOrbit */ inline T& operator[](uint32 i) { - cgogn_message_assert(is_valid(), "Invalid AttributeHandler"); + cgogn_message_assert(is_valid(), "Invalid Attribute"); return chunk_array_->operator[](i); } @@ -395,18 +420,28 @@ class AttributeHandler : public AttributeHandlerOrbit */ inline const T& operator[](uint32 i) const { - cgogn_message_assert(is_valid(), "Invalid AttributeHandler"); + cgogn_message_assert(is_valid(), "Invalid Attribute"); return chunk_array_->operator[](i); } + /** + * @brief set_value method to write in boolean Attributes + * @param i + * @param t + */ + inline void set_value(uint32 i, const T& t) + { + chunk_array_->set_value(i, t); + } + class const_iterator { public: - const AttributeHandler* const ah_ptr_; + const Attribute* const ah_ptr_; uint32 index_; - inline const_iterator(const AttributeHandler* ah, uint32 i) : + inline const_iterator(const Attribute* ah, uint32 i) : ah_ptr_(ah), index_(i) {} @@ -455,10 +490,10 @@ class AttributeHandler : public AttributeHandlerOrbit class iterator { public: - AttributeHandler* const ah_ptr_; + Attribute* const ah_ptr_; uint32 index_; - inline iterator(AttributeHandler* ah, uint32 i) : + inline iterator(Attribute* ah, uint32 i) : ah_ptr_(ah), index_(i) {} @@ -502,8 +537,15 @@ class AttributeHandler : public AttributeHandlerOrbit { return iterator(this, this->chunk_array_cont_->end()); } + + virtual const std::string& get_type_name() const override + { + return chunk_array_->get_type_name(); + } }; + + } // namespace cgogn -#endif // CORE_MAP_ATTRIBUTE_HANDLER_H_ +#endif // CGOGN_CORE_MAP_ATTRIBUTE_H_ diff --git a/cgogn/core/cmap/cmap0.cpp b/cgogn/core/cmap/cmap0.cpp index e6eda691..651633c4 100644 --- a/cgogn/core/cmap/cmap0.cpp +++ b/cgogn/core/cmap/cmap0.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_CORE_DLL_EXPORT -#define CORE_MAP_MAP0_CPP_ +#define CGOGN_CORE_MAP_MAP0_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index 9e812298..6697f8cf 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -21,10 +21,10 @@ * * *******************************************************************************/ -#ifndef CORE_CMAP_CMAP0_H_ -#define CORE_CMAP_CMAP0_H_ +#ifndef CGOGN_CORE_CMAP_CMAP0_H_ +#define CGOGN_CORE_CMAP_CMAP0_H_ -#include +#include namespace cgogn { @@ -34,7 +34,7 @@ class CMap0_T : public MapBase { public: - static const int32 PRIM_SIZE = 1; + static const uint8 PRIM_SIZE = 1; using MapTraits = MAP_TRAITS; using MapType = MAP_TYPE; @@ -46,7 +46,9 @@ class CMap0_T : public MapBase friend class cgogn::DartMarkerStore; using Vertex = Cell; + using Boundary = Vertex; // just for compilation + using ConnectedComponent = Vertex; template using ChunkArray = typename Inherit::template ChunkArray; @@ -54,9 +56,9 @@ class CMap0_T : public MapBase using ChunkArrayContainer = typename Inherit::template ChunkArrayContainer; template - using AttributeHandler = typename Inherit::template AttributeHandler; + using Attribute = typename Inherit::template Attribute; template - using VertexAttributeHandler = AttributeHandler; + using VertexAttribute = Attribute; using DartMarker = typename cgogn::DartMarker; using DartMarkerStore = typename cgogn::DartMarkerStore; @@ -100,10 +102,28 @@ class CMap0_T : public MapBase { } + /** + * @brief Check the integrity of a dart + * @param d the dart to check + * @return true if the integrity constraints are locally statisfied + * No contraints. + */ inline bool check_integrity(Dart) const { return true; } + + /** + * @brief Check the integrity of a boundary dart + * @param d the dart to check + * @return true if the bondary constraints are locally statisfied + * No boundary dart is accepted. + */ + inline bool check_boundary_integrity(Dart d) const + { + return !this->is_boundary(d); + } + /******************************************************************************* * High-level embedded and topological operations *******************************************************************************/ @@ -156,6 +176,36 @@ class CMap0_T : public MapBase static_assert(ORBIT == Orbit::DART, "Orbit not supported in a CMap0"); f(c.dart); } + +protected: + + /** + * @brief check if embedding of map is also embedded in this (create if not). Used by merge method + * @param map + */ + void merge_check_embedding(const Self& map) + { + if (!this->template is_embedded() && map.template is_embedded()) + this->template create_embedding(); + } + + /** + * @brief ensure all cells (introduced while merging) are embedded. + * @param first index of first dart to scan + */ + void merge_finish_embedding(uint32 first) + { + if (this->template is_embedded()) + { + for (uint32 j=first; j!= this->topology_.end(); this->topology_.next(j)) + { + if ((*this->embeddings_[Orbit::DART])[j] == std::numeric_limits::max()) + this->new_orbit_embedding(Cell(Dart(j))); + } + } + } + + }; template @@ -167,15 +217,15 @@ struct CMap0Type template using CMap0 = CMap0_T>; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP0_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_CORE_MAP_MAP0_CPP_)) extern template class CGOGN_CORE_API CMap0_T>; extern template class CGOGN_CORE_API DartMarker>; extern template class CGOGN_CORE_API DartMarkerStore>; extern template class CGOGN_CORE_API DartMarkerNoUnmark>; extern template class CGOGN_CORE_API CellMarker, CMap0::Vertex::ORBIT>; extern template class CGOGN_CORE_API CellMarkerStore, CMap0::Vertex::ORBIT>; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP0_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_CORE_MAP_MAP0_CPP_)) } // namespace cgogn -#endif // CORE_CMAP_CMAP0_H_ +#endif // CGOGN_CORE_CMAP_CMAP0_H_ diff --git a/cgogn/core/cmap/cmap1.cpp b/cgogn/core/cmap/cmap1.cpp index 6558862f..850de1e4 100644 --- a/cgogn/core/cmap/cmap1.cpp +++ b/cgogn/core/cmap/cmap1.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_CORE_DLL_EXPORT -#define CORE_MAP_MAP1_CPP_ +#define CGOGN_CORE_MAP_MAP1_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 8328c3eb..9efb2f28 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -21,39 +21,22 @@ * * *******************************************************************************/ -#ifndef CORE_CMAP_CMAP1_H_ -#define CORE_CMAP_CMAP1_H_ +#ifndef CGOGN_CORE_CMAP_CMAP1_H_ +#define CGOGN_CORE_CMAP_CMAP1_H_ -#include +#include namespace cgogn { -namespace internal -{ -template -struct check_multi_phi -{ - static const bool value_cmap1 = (N<10)?(N%10>0) && (N%10<=1):(N%10>0) && (N%10<=2) && check_multi_phi::value_cmap1; - static const bool value_cmap2 = (N<10)?(N%10>0) && (N%10<=2):(N%10>0) && (N%10<=2) && check_multi_phi::value_cmap2; - static const bool value_cmap3 = (N<10)?(N%10>0) && (N%10<=3):(N%10>0) && (N%10<=3) && check_multi_phi::value_cmap3; - -}; -template<> -struct check_multi_phi<0> -{ - static const bool value_cmap1 = true; - static const bool value_cmap2 = true; - static const bool value_cmap3 = true; -}; -} - template class CMap1_T : public CMap0_T { public: - static const int32 PRIM_SIZE = 1; + static const uint8 DIMENSION = 1; + + static const uint8 PRIM_SIZE = 1; using MapTraits = MAP_TRAITS; using MapType = MAP_TYPE ; @@ -68,6 +51,7 @@ class CMap1_T : public CMap0_T using Face = Cell; using Boundary = Vertex; + using ConnectedComponent = Face; template using ChunkArray = typename Inherit::template ChunkArray; @@ -75,11 +59,11 @@ class CMap1_T : public CMap0_T using ChunkArrayContainer = typename Inherit::template ChunkArrayContainer; template - using AttributeHandler = typename Inherit::template AttributeHandler; + using Attribute = typename Inherit::template Attribute; template - using VertexAttributeHandler = AttributeHandler; + using VertexAttribute = Attribute; template - using FaceAttributeHandler = AttributeHandler; + using FaceAttribute = Attribute; using DartMarker = typename cgogn::DartMarker; using DartMarkerStore = typename cgogn::DartMarkerStore; @@ -143,12 +127,29 @@ class CMap1_T : public CMap0_T (*phi_1_)[d.index] = d; } + /** + * @brief Check the integrity of a dart + * @param d the dart to check + * @return true if the integrity constraints are locally statisfied + * PHI1 and PHI_1 are inverse relations. + */ inline bool check_integrity(Dart d) const { return (phi1(phi_1(d)) == d && phi_1(phi1(d)) == d); } + /** + * @brief Check the integrity of a boundary dart + * @param d the dart to check + * @return true if the bondary constraints are locally statisfied + * No boundary dart is accepted. + */ + inline bool check_boundary_integrity(Dart d) const + { + return !this->is_boundary(d); + } + /*! * \brief Link two darts with the phi1 permutation what either merge or split their orbit(s). * @param d: the first dart @@ -215,18 +216,17 @@ class CMap1_T : public CMap0_T return (*phi_1_)[d.index]; } - - /** - * \brief phi composition + * \brief Composition of PHI calls * @param d - * @return applied composition of phi in order of declaration + * @return The result of successive applications of PHI1 on d. + * The template parameter contains a sequence (Base10 encoded) of PHI indices. + * If N=0 the identity is used. */ template inline Dart phi(Dart d) const { - static_assert(internal::check_multi_phi::value_cmap1, "composition on phi1 only"); - + static_assert((N%10)<=1,"Composition of PHI: invalid index"); if (N >=10) return this->phi1(phi(d)); @@ -236,8 +236,6 @@ class CMap1_T : public CMap0_T return d; } - - /******************************************************************************* * High-level embedded and topological operations *******************************************************************************/ @@ -290,15 +288,10 @@ class CMap1_T : public CMap0_T return f; } - /*! - * \brief Remove a face from the map. - * \param d : a dart of the face to remove - */ - inline void remove_face(Face f) - { - CGOGN_CHECK_CONCRETE_TYPE; +protected: - Dart d = f.dart; + inline void remove_face_topo(Dart d) + { Dart it = phi1(d); while(it != d) { @@ -310,6 +303,19 @@ class CMap1_T : public CMap0_T this->remove_dart(d); } +public: + + /*! + * \brief Remove a face from the map. + * \param d : a dart of the face to remove + */ + inline void remove_face(Face f) + { + CGOGN_CHECK_CONCRETE_TYPE; + + remove_face_topo(f.dart); + } + protected: /** @@ -350,18 +356,32 @@ class CMap1_T : public CMap0_T return nv; } +protected: + + /** + * \brief Remove a vertex from its face and delete it. + * @param d : a dart of the vertex + * The vertex that preceeds the vertex of d in the face is linked + * to the successor of the vertex of d. + */ + inline void remove_vertex_topo(Dart d) + { + Dart e = phi_1(d); + if (e != d) phi1_unsew(e); + this->remove_dart(d); + } + +public: + /** * \brief Remove a vertex from its face and delete it. * @param v : a vertex - * The vertex that preceeds v in the face is linked to the successor of v. */ inline void remove_vertex(Vertex v) { CGOGN_CHECK_CONCRETE_TYPE; - Dart e = phi_1(v.dart); - if (e != v.dart) phi1_unsew(e); - this->remove_dart(v.dart); + remove_vertex_topo(v.dart); } protected: @@ -391,10 +411,9 @@ class CMap1_T : public CMap0_T public: - - inline uint32 degree(Vertex ) const + inline uint32 degree(Vertex) const { - return 2; + return 1; } inline uint32 codegree(Face f) const @@ -405,8 +424,9 @@ class CMap1_T : public CMap0_T inline bool has_codegree(Face f, uint32 codegree) const { + if (codegree < 1u) return false; Dart it = f.dart ; - for (uint32 i = 1; i < codegree; ++i) + for (uint32 i = 1u; i < codegree; ++i) { it = phi1(it) ; if (it == f.dart) @@ -449,6 +469,7 @@ class CMap1_T : public CMap0_T case Orbit::PHI2_PHI3: case Orbit::PHI21: case Orbit::PHI21_PHI31: + case Orbit::PHI1_PHI2_PHI3: default: cgogn_assert_not_reached("Orbit not supported in a CMap1"); break; } } @@ -482,6 +503,7 @@ class CMap1_T : public CMap0_T case Orbit::PHI2_PHI3: case Orbit::PHI21: case Orbit::PHI21_PHI31: + case Orbit::PHI1_PHI2_PHI3: default: cgogn_assert_not_reached("Orbit not supported in a CMap1"); break; } } @@ -498,8 +520,44 @@ class CMap1_T : public CMap0_T static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); foreach_dart_of_orbit(f, [&func](Dart v) {func(Vertex(v));}); } -}; +protected: + + /** + * @brief check if embedding of map is also embedded in this (create if not). Used by merge method + * @param map + */ + void merge_check_embedding(const Self& map) + { + if (!this->template is_embedded() && map.template is_embedded()) + this->template create_embedding(); + if (!this->template is_embedded() && map.template is_embedded()) + this->template create_embedding(); + + } + + /** + * @brief ensure all cells (introduced while merging) are embedded. + * @param first index of first dart to scan + */ + void merge_finish_embedding(uint32 first) + { + if (this->template is_embedded()) + for (uint32 j=first; j!= this->topology_.end(); this->topology_.next(j)) + { + if ((*this->embeddings_[Orbit::DART])[j] == std::numeric_limits::max()) + this->new_orbit_embedding(Cell(Dart(j))); + } + + if (this->template is_embedded()) + for (uint32 j=first; j!= this->topology_.end(); this->topology_.next(j)) + { + if ((*this->embeddings_[Orbit::PHI1])[j] == std::numeric_limits::max()) + this->new_orbit_embedding(Cell(Dart(j))); + } + } + +}; template struct CMap1Type @@ -510,7 +568,7 @@ struct CMap1Type template using CMap1 = CMap1_T>; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP1_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_CORE_MAP_MAP1_CPP_)) extern template class CGOGN_CORE_API CMap1_T>; extern template class CGOGN_CORE_API DartMarker>; extern template class CGOGN_CORE_API DartMarkerStore>; @@ -519,10 +577,8 @@ extern template class CGOGN_CORE_API CellMarker, CMap1, CMap1::Face::ORBIT>; extern template class CGOGN_CORE_API CellMarkerStore, CMap1::Vertex::ORBIT>; extern template class CGOGN_CORE_API CellMarkerStore, CMap1::Face::ORBIT>; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP1_CPP_)) - - +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_CORE_MAP_MAP1_CPP_)) } // namespace cgogn -#endif // CORE_CMAP_CMAP1_H_ +#endif // CGOGN_CORE_CMAP_CMAP1_H_ diff --git a/cgogn/core/cmap/cmap2.cpp b/cgogn/core/cmap/cmap2.cpp index c477312f..fc2bb010 100644 --- a/cgogn/core/cmap/cmap2.cpp +++ b/cgogn/core/cmap/cmap2.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_CORE_DLL_EXPORT -#define CORE_MAP_MAP2_CPP_ +#define CGOGN_CORE_MAP_MAP2_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 36c38a12..974d6b85 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -21,10 +21,10 @@ * * *******************************************************************************/ -#ifndef CORE_CMAP_CMAP2_H_ -#define CORE_CMAP_CMAP2_H_ +#ifndef CGOGN_CORE_CMAP_CMAP2_H_ +#define CGOGN_CORE_CMAP_CMAP2_H_ -#include +#include namespace cgogn { @@ -36,8 +36,9 @@ template class CMap2_T : public CMap1_T { public: + static const uint8 DIMENSION = 2; - static const int32 PRIM_SIZE = 1; + static const uint8 PRIM_SIZE = 1; using MapTraits = MAP_TRAITS; using MapType = MAP_TYPE; @@ -56,6 +57,7 @@ class CMap2_T : public CMap1_T using Volume = Cell; using Boundary = Face; + using ConnectedComponent = Volume; template using ChunkArray = typename Inherit::template ChunkArray; @@ -63,15 +65,15 @@ class CMap2_T : public CMap1_T using ChunkArrayContainer = typename Inherit::template ChunkArrayContainer; template - using AttributeHandler = typename Inherit::template AttributeHandler; + using Attribute = typename Inherit::template Attribute; template - using VertexAttributeHandler = AttributeHandler; + using VertexAttribute = Attribute; template - using EdgeAttributeHandler = AttributeHandler; + using EdgeAttribute = Attribute; template - using FaceAttributeHandler = AttributeHandler; + using FaceAttribute = Attribute; template - using VolumeAttributeHandler = AttributeHandler; + using VolumeAttribute = Attribute; using DartMarker = typename cgogn::DartMarker; using DartMarkerStore = typename cgogn::DartMarkerStore; @@ -145,15 +147,26 @@ class CMap2_T : public CMap1_T * @brief Check the integrity of a dart * @param d the dart to check * @return true if the integrity constraints are locally statisfied - * PHI2 should be an involution without fixed poit and - * the boundary marker is identical for all darts of a face. + * PHI2 should be an involution without fixed point */ inline bool check_integrity(Dart d) const { return (Inherit::check_integrity(d) && phi2(phi2(d)) == d && - phi2(d) != d && - ( this->is_boundary(d) == this->is_boundary(this->phi1(d)) )); + phi2(d) != d); + } + + /** + * @brief Check the integrity of a boundary dart + * @param d the dart to check + * @return true if the bondary constraints are locally statisfied + * The boundary is a 1-manifold: the boundary marker is the same + * for all darts of a face and two boundary faces cannot be adjacent. + */ + inline bool check_boundary_integrity(Dart d) const + { + return (( this->is_boundary(d) == this->is_boundary(this->phi1(d)) ) && + ( !this->is_boundary(d) || !this->is_boundary(this->phi2(d)) )); } /** @@ -201,18 +214,20 @@ class CMap2_T : public CMap1_T /** - * \brief phi composition + * \brief Composition of PHI calls * @param d - * @return applied composition of phi in order of declaration + * @return The result of successive applications of PHI1 and PHI2 on d. + * The template parameter contains a sequence (Base10 encoded) of PHI indeices. + * If N=0 the identity is used. */ template inline Dart phi(Dart d) const { - static_assert(internal::check_multi_phi::value_cmap2, "composition on phi1/phi2/only"); - switch(N%10) + static_assert((N % 10) <= 2, "Composition of PHI: invalid index"); + switch(N % 10) { - case 1 : return this->phi1(phi(d)) ; - case 2 : return this->phi2(phi(d)) ; + case 1 : return this->phi1(phi(d)) ; + case 2 : return this->phi2(phi(d)) ; default : return d ; } } @@ -223,7 +238,7 @@ class CMap2_T : public CMap1_T protected: - /*! + /** * \brief Add a face in the map. * \param size : the number of darts in the built face * \return A dart of the built face. @@ -235,21 +250,19 @@ class CMap2_T : public CMap1_T Dart d = Inherit::add_face_topo(size); Dart e = Inherit::add_face_topo(size); - Dart it = d; - do + this->foreach_dart_of_PHI1(d, [&] (Dart it) { this->set_boundary(e, true); phi2_sew(it, e); - it = this->phi1(it); e = this->phi_1(e); - } while (it != d); + }); return d; } public: - /*! + /** * \brief Add a face in the map. * \param size : the number of edges in the built face * \return The built face @@ -269,7 +282,6 @@ class CMap2_T : public CMap1_T foreach_dart_of_orbit(f, [this] (Dart d) { this->new_orbit_embedding(CDart(d)); -// this->new_orbit_embedding(CDart(phi2(d))); }); } @@ -290,10 +302,7 @@ class CMap2_T : public CMap1_T } if (this->template is_embedded()) - { this->new_orbit_embedding(f); -// this->new_orbit_embedding(Face(phi2(f.dart))); - } if (this->template is_embedded()) this->new_orbit_embedding(Volume(f.dart)); @@ -303,6 +312,62 @@ class CMap2_T : public CMap1_T protected: + /** + * \brief Add a pyramid whose base has n sides. + * \param size : the number of darts in the base face + * \return A dart of the base face + * The base is a face with n vertices and edges. + * Each edge is adjacent to a triangular face. + * These triangles are pairwise sewn to build the top of the pyramid. + */ + inline Dart add_pyramid_topo(uint32 size) + { + cgogn_message_assert(size > 0u, "The pyramid cannot be empty"); + + Dart first = this->Inherit::add_face_topo(3u); // First triangle + Dart current = first; + + for (uint32 i = 1u; i < size; ++i) // Next triangles + { + Dart next = this->Inherit::add_face_topo(3u); + this->phi2_sew(this->phi_1(current), this->phi1(next)); + current = next; + } + // End the umbrella + this->phi2_sew(this->phi_1(current), this->phi1(first)); + + return this->close_hole_topo(first); // Add the base face + } + + /** + * \brief Add a prism with n sides. + * \param size : the number of sides of the prism + * \return A dart of the base face + * The base and the top are faces with n vertices and edges. + * A set of n pairwise linked quads are built. + * These quads are sewn to the base and top faces. + */ + Dart add_prism_topo(uint32 size) + { + cgogn_message_assert(size > 0u, "The prism cannot be empty"); + + Dart first = this->Inherit::add_face_topo(4u); // First quad + Dart current = first; + + for (uint32 i = 1u; i < size; ++i) // Next quads + { + Dart next = this->Inherit::add_face_topo(4u); + this->phi2_sew(this->phi_1(current), this->phi1(next)); + current = next; + } + + this->phi2_sew(this->phi_1(current), this->phi1(first));// Close the quad strip + + this->close_hole_topo(this->phi1(this->phi1(first))); // Add the top face + + return this->close_hole_topo(first); // Add the base face + } + /** * \brief Cut an edge. * \param d : A dart that represents the edge to cut @@ -384,6 +449,117 @@ class CMap2_T : public CMap1_T return Vertex(v); } +protected: + + /** + * @brief Flip an edge + * @param d : a dart of the edge to flip + * @return true if the edge has been flipped, false otherwise + * Each end of the edge is detached from its initial vertex + * and inserted in the next vertex within its incident face. + * An end of the edge that is a vertex of degree 1 is not moved. + * If one of the faces have co-degree 1 then nothing is done. + */ + inline bool flip_edge_topo(Dart d) + { + Dart e = phi2(d); + if (!this->is_boundary(d) && !this->is_boundary(e)) + { + Dart d1 = this->phi1(d); + Dart d11 = this->phi1(d1); + Dart d_1 = this->phi_1(d); + Dart e1 = this->phi1(e); + Dart e11 = this->phi1(e1); + Dart e_1 = this->phi_1(e); + + // Cannot flip edge whose incident faces have co-degree 1 + if (d == d1 || e == e1 ) return false; + + // Both vertices have degree 1 and thus nothing is done // TODO may return true ? + if (d == e_1 && e == d_1) return false; + + if (d != e_1) this->phi1_sew(d, e_1); // Detach the edge from its + if (e != d_1) this->phi1_sew(e, d_1); // two incident vertices + + if (d != e_1) this->phi1_sew(d, d1); // Insert the first end in its new vertices + if (e != d_1) this->phi1_sew(e, e1); // Insert the second end in its new vertices + + return true; + } + return false; + } + +public: + + /** + * @brief Flip an edge + * @param e : the edge to flip + * The two endpoints of the given edge are moved to the next vertices + * of their two adjacent faces + */ + inline void flip_edge(Edge e) + { + CGOGN_CHECK_CONCRETE_TYPE; + + if (flip_edge_topo(e.dart)) + { + Dart d = e.dart; + Dart d2 = phi2(d); + + if (this->template is_embedded()) + { + this->template copy_embedding(d, this->phi1(d2)); + this->template copy_embedding(d2, this->phi1(d)); + } + + if (this->template is_embedded()) + { + this->template copy_embedding(this->phi_1(d), d); + this->template copy_embedding(this->phi_1(d2), d2); + } + } + } + +protected: + + /** + * @brief Collapse an edge + * @param d : a dart of the edge to collapse + * @return a dart of the resulting vertex + */ + inline Dart collapse_edge_topo(Dart d) + { + Dart res = phi2(this->phi_1(d)); + + Dart e = phi2(d); + this->remove_vertex_topo(d); + this->remove_vertex_topo(e); + + return res; + } + +public: + + /** + * @brief Collapse an edge + * @param e : the edge to collapse + * @return the resulting vertex + */ + inline Vertex collapse_edge(Edge e) + { + CGOGN_CHECK_CONCRETE_TYPE; + + Vertex v(collapse_edge_topo(e.dart)); + + if (this->template is_embedded()) + { + uint32 emb = this->get_embedding(v); + foreach_dart_of_orbit(v, [this, emb] (Dart d) { this->template set_embedding(d, emb); }); + } + + return v; + } + protected: void merge_adjacent_edges_topo(Dart d) @@ -400,8 +576,6 @@ class CMap2_T : public CMap1_T // TODO } -protected: - /** * \brief Cut the face of d and e by inserting an edge between the vertices of d and e * \param d : first vertex @@ -445,7 +619,7 @@ class CMap2_T : public CMap1_T CGOGN_CHECK_CONCRETE_TYPE; cgogn_message_assert(!this->is_boundary(d.dart), "cut_face: should not cut a boundary face"); - cut_face_topo(d.dart,e.dart); + cut_face_topo(d.dart, e.dart); Dart nd = this->phi_1(d.dart); Dart ne = this->phi_1(e.dart); @@ -477,18 +651,129 @@ class CMap2_T : public CMap1_T } } +protected: + + inline bool unsew_faces_topo(Edge g) + { + if (this->is_incident_to_boundary(g)) + return false; + + Dart d = g.dart; + Dart dd = phi2(d); + + Dart e = Inherit::add_face_topo(2); + Dart ee = this->phi1(e); + this->set_boundary(e, true); + this->set_boundary(ee, true); + + Dart f = this->get_boundary_dart(Vertex(d)); + Dart ff = this->get_boundary_dart(Vertex(dd)); + + if(!f.is_nil()) + this->phi1_sew(e, this->phi_1(f)); + + if(!ff.is_nil()) + this->phi1_sew(ee, this->phi_1(ff)); + + phi2_unsew(d); + + phi2_sew(d, e); + phi2_sew(dd, ee); + + return true; + } + +public: + + inline void unsew_faces(Edge d) + { + Dart e = phi2(d.dart); + if (unsew_faces_topo(d)) + { + if (this->template is_embedded()) + { + Dart ee = this->phi1(e); + if (this->same_orbit(Vertex(d.dart), Vertex(ee))) + this->template copy_embedding(phi2(e), ee); + else + this->new_orbit_embedding(Vertex(ee)); + + Dart dd = this->phi1(d.dart); + if (this->same_orbit(Vertex(e), Vertex(dd))) + this->template copy_embedding(phi2(d.dart), dd); + else + this->new_orbit_embedding(Vertex(dd)); + } + + if (this->template is_embedded()) + this->new_orbit_embedding(Edge(e)); + + if (this->template is_embedded()) + { + if (this->same_orbit(Volume(d.dart), Volume(e))) + { + this->template copy_embedding(phi2(e), e); + this->template copy_embedding(phi2(d.dart), e); + } + else + this->new_orbit_embedding(Volume(e)); + } + } + } + +protected: + + /*! + * \brief Close the topological hole that contains Dart d (a fixed point for PHI2). + * \param d : a vertex of the hole + * \return a vertex of the face that closes the hole + * This method is used to close a CMap2 that has been build through the 2-sewing of 1-faces. + * A face is inserted on the boundary that begin at dart d. + */ + inline Dart close_hole_topo(Dart d) + { + cgogn_message_assert(phi2(d) == d, "CMap2: close hole called on a dart that is not a phi2 fix point"); + + Dart first = this->add_dart(); // First edge of the face that will fill the hole + phi2_sew(d, first); // 2-sew the new edge to the hole + + Dart d_next = d; // Turn around the hole + Dart d_phi1; // to complete the face + do + { + do + { + d_phi1 = this->phi1(d_next); // Search and put in d_next + d_next = phi2(d_phi1); // the next dart of the hole + } while (d_next != d_phi1 && d_phi1 != d); + + if (d_phi1 != d) + { + Dart next = this->split_vertex_topo(first); // Add a vertex into the built face + phi2_sew(d_next, next); // and 2-sew the face to the hole + } + } while (d_phi1 != d); + + return first; + } + /******************************************************************************* * Connectivity information *******************************************************************************/ +public: + inline uint32 degree(Vertex v) const { return this->nb_darts_of_orbit(v); } - inline uint32 codegree(Edge) const + inline uint32 codegree(Edge e) const { - return 2; + if (this->phi1(e.dart) == e.dart) + return 1; + else + return 2; } inline uint32 degree(Edge e) const @@ -516,6 +801,23 @@ class CMap2_T : public CMap1_T return result; } + /******************************************************************************* + * Boundary information + *******************************************************************************/ + + bool is_adjacent_to_boundary(Boundary c) + { + CGOGN_CHECK_CONCRETE_TYPE; + + bool result = false; + foreach_dart_of_orbit_until(c, [this, &result] (Dart d) + { + if (this->is_boundary(phi2(d))) { result = true; return false; } + return true; + }); + return result; + } + /******************************************************************************* * Orbits traversal *******************************************************************************/ @@ -589,6 +891,7 @@ class CMap2_T : public CMap1_T case Orbit::PHI2_PHI3: case Orbit::PHI1_PHI3: case Orbit::PHI21_PHI31: + case Orbit::PHI1_PHI2_PHI3: default: cgogn_assert_not_reached("Orbit not supported in a CMap2"); break; } } @@ -667,6 +970,7 @@ class CMap2_T : public CMap1_T case Orbit::PHI2_PHI3: case Orbit::PHI1_PHI3: case Orbit::PHI21_PHI31: + case Orbit::PHI1_PHI2_PHI3: default: cgogn_assert_not_reached("Orbit not supported in a CMap2"); break; } } @@ -884,11 +1188,59 @@ class CMap2_T : public CMap1_T }); } - inline std::pair vertices(Edge e) + inline std::pair vertices(Edge e) const + { + return std::pair(Vertex(e.dart), Vertex(this->phi1(e.dart))); + } + +protected: + +#define FOR_ALL_ORBITS( CODE) {\ +{static const Orbit orbit_const=DART; CODE }\ +{static const Orbit orbit_const=PHI1; CODE }\ +{static const Orbit orbit_const=PHI2; CODE }\ +{static const Orbit orbit_const=PHI1_PHI2; CODE }\ +{static const Orbit orbit_const=PHI21; CODE }} + + + /** + * @brief check if embedding of map is also embedded in this (create if not). Used by merge method + * @param map + */ + void merge_check_embedding(const Self& map) { - return std::pair(Vertex(e.dart),Vertex(this->phi1(e.dart))); + FOR_ALL_ORBITS + ( + if (!this->template is_embedded() && map.template is_embedded()) + this->template create_embedding(); + ) } + + /** + * @brief ensure all cells (introduced while merging) are embedded. + * @param first index of first dart to scan + */ + void merge_finish_embedding(uint32 first) + { + FOR_ALL_ORBITS + ( + if (this->template is_embedded()) + { + for (uint32 j=first; j!= this->topology_.end(); this->topology_.next(j)) + { + if ( ((orbit_const != Boundary::ORBIT) && (orbit_const != DART)) || (!this->is_boundary(Dart(j)))) + if ((*this->embeddings_[orbit_const])[j] == INVALID_INDEX) + { + this->new_orbit_embedding(Cell(Dart(j))); + } + } + } + ) + } + +#undef FOR_ALL_ORBITS + }; template @@ -900,7 +1252,7 @@ struct CMap2Type template using CMap2 = CMap2_T>; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP2_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_CORE_MAP_MAP2_CPP_)) extern template class CGOGN_CORE_API CMap2_T>; extern template class CGOGN_CORE_API DartMarker>; extern template class CGOGN_CORE_API DartMarkerStore>; @@ -913,8 +1265,8 @@ extern template class CGOGN_CORE_API CellMarkerStore, CM extern template class CGOGN_CORE_API CellMarkerStore, CMap2::Edge::ORBIT>; extern template class CGOGN_CORE_API CellMarkerStore, CMap2::Face::ORBIT>; extern template class CGOGN_CORE_API CellMarkerStore, CMap2::Volume::ORBIT>; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP2_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_CORE_MAP_MAP2_CPP_)) } // namespace cgogn -#endif // CORE_CMAP_CMAP2_H_ +#endif // CGOGN_CORE_CMAP_CMAP2_H_ diff --git a/cgogn/core/cmap/cmap2_builder.cpp b/cgogn/core/cmap/cmap2_builder.cpp index 1252cb02..79ce1878 100644 --- a/cgogn/core/cmap/cmap2_builder.cpp +++ b/cgogn/core/cmap/cmap2_builder.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_CORE_DLL_EXPORT -#define CORE_MAP_MAP2_BUILDER_CPP_ +#define CGOGN_CORE_MAP_MAP2_BUILDER_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/core/cmap/cmap2_builder.h b/cgogn/core/cmap/cmap2_builder.h index a4301250..6fae9b5a 100644 --- a/cgogn/core/cmap/cmap2_builder.h +++ b/cgogn/core/cmap/cmap2_builder.h @@ -21,10 +21,10 @@ * * *******************************************************************************/ -#ifndef CORE_MAP_MAP2_BUILDER_H_ -#define CORE_MAP_MAP2_BUILDER_H_ +#ifndef CGOGN_CORE_MAP_MAP2_BUILDER_H_ +#define CGOGN_CORE_MAP_MAP2_BUILDER_H_ -#include +#include namespace cgogn { @@ -47,6 +47,7 @@ class CMap2Builder_T inline CMap2Builder_T(CMap2& map) : map_(map) {} + CGOGN_NOT_COPYABLE_NOR_MOVABLE(CMap2Builder_T); public: @@ -90,38 +91,9 @@ class CMap2Builder_T return map_.CMap2::Inherit::add_face_topo(nb_edges); } - /*! - * \brief Close the topological hole that contains Dart d (a fixed point for PHI2). - * \param d : a vertex of the hole - * \return a vertex of the face that close the hole - * This method is used to close a CMap2 that has been build through the 2-sewing of 1-faces. - * A face is inserted on the boundary that begin at dart d. - */ inline Dart close_hole_topo(Dart d) { - cgogn_message_assert(map_.phi2(d) == d, "CMap2: close hole called on a dart that is not a phi2 fix point"); - - Dart first = map_.add_dart(); // First edge of the face that will fill the hole - map_.phi2_sew(d, first); // 2-sew the new edge to the hole - - Dart d_next = d; // Turn around the hole - Dart d_phi1; // to complete the face - do - { - do - { - d_phi1 = map_.phi1(d_next); // Search and put in d_next - d_next = map_.phi2(d_phi1); // the next dart of the hole - } while (d_next != d_phi1 && d_phi1 != d); - - if (d_phi1 != d) - { - Dart next = map_.split_vertex_topo(first); // Add a vertex into the built face - phi2_sew(d_next, next); // and 2-sew the face to the hole - } - } while (d_phi1 != d); - - return first; + return map_.close_hole_topo(d); } /*! @@ -137,7 +109,7 @@ class CMap2Builder_T */ inline Face close_hole(Dart d) { - const Face f(close_hole_topo(d)); + const Face f(map_.close_hole_topo(d)); // if (map_.template is_embedded()) // { @@ -215,13 +187,13 @@ class CMap2Builder_T CMap2& map_; }; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP2_BUILDER_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_CORE_MAP_MAP2_BUILDER_CPP_)) extern template class CGOGN_CORE_API cgogn::CMap2Builder_T; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP2_BUILDER_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_CORE_MAP_MAP2_BUILDER_CPP_)) using CMap2Builder = cgogn::CMap2Builder_T; } // namespace cgogn -#endif // CORE_MAP_MAP2_BUILDER_H_ +#endif // CGOGN_CORE_MAP_MAP2_BUILDER_H_ diff --git a/cgogn/core/cmap/cmap3.cpp b/cgogn/core/cmap/cmap3.cpp index fe164fdd..a034cd96 100644 --- a/cgogn/core/cmap/cmap3.cpp +++ b/cgogn/core/cmap/cmap3.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_CORE_DLL_EXPORT -#define CORE_MAP_MAP3_CPP_ +#define CGOGN_CORE_MAP_MAP3_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 90cd4551..0316c798 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -21,10 +21,10 @@ * * *******************************************************************************/ -#ifndef CORE_CMAP_CMAP3_H_ -#define CORE_CMAP_CMAP3_H_ +#ifndef CGOGN_CORE_CMAP_CMAP3_H_ +#define CGOGN_CORE_CMAP_CMAP3_H_ -#include +#include namespace cgogn { @@ -37,7 +37,9 @@ class CMap3_T : public CMap2_T { public: - static const int32 PRIM_SIZE = 1; + static const uint8 DIMENSION = 3; + + static const uint8 PRIM_SIZE = 1; using MapTraits = MAP_TRAITS; using MapType = MAP_TYPE; @@ -59,6 +61,7 @@ class CMap3_T : public CMap2_T using Volume = typename Inherit::Volume; using Boundary = Volume; + using ConnectedComponent = Cell; template using ChunkArray = typename Inherit::template ChunkArray; @@ -66,15 +69,15 @@ class CMap3_T : public CMap2_T using ChunkArrayContainer = typename Inherit::template ChunkArrayContainer; template - using AttributeHandler = typename Inherit::template AttributeHandler; + using Attribute = typename Inherit::template Attribute; template - using VertexAttributeHandler = AttributeHandler; + using VertexAttribute = Attribute; template - using EdgeAttributeHandler = AttributeHandler; + using EdgeAttribute = Attribute; template - using FaceAttributeHandler = AttributeHandler; + using FaceAttribute = Attribute; template - using VolumeAttributeHandler = AttributeHandler; + using VolumeAttribute = Attribute; using DartMarker = typename cgogn::DartMarker; using DartMarkerStore = typename cgogn::DartMarkerStore; @@ -153,12 +156,32 @@ class CMap3_T : public CMap2_T (*phi3_)[d.index] = d; } + /** + * @brief Check the integrity of a dart + * @param d the dart to check + * @return true if the integrity constraints are locally statisfied + * PHI3_PHI1 should be an involution without fixed point and + */ inline bool check_integrity(Dart d) const { return (Inherit::check_integrity(d) && phi3(phi3(d)) == d && phi3(d) != d && - phi3(this->phi1(phi3(this->phi1(d)))) == d); + phi3(this->phi1(phi3(this->phi1(d)))) == d && + ( this->is_boundary(d) == this->is_boundary(this->phi2(d)) )); + } + + /** + * @brief Check the integrity of a boundary dart + * @param d the dart to check + * @return true if the bondary constraints are locally statisfied + * The boundary is a 2-manyfold: the boundary marker is the same + * for all darts of a face and for two adjacent faces. + */ + inline bool check_boundary_integrity(Dart d) const + { + return (( this->is_boundary(d) == this->is_boundary(this->phi1(d)) ) && + ( this->is_boundary(d) == this->is_boundary(this->phi2(d)) )); } /** @@ -204,8 +227,6 @@ class CMap3_T : public CMap2_T return (*phi3_)[d.index]; } - - /** * \brief phi composition * @param d @@ -214,7 +235,7 @@ class CMap3_T : public CMap2_T template inline Dart phi(Dart d) const { - static_assert(internal::check_multi_phi::value_cmap3, "composition on phi1/phi2/phi3 only"); + static_assert((N%10)<=3,"composition on phi1/phi2/only"); switch(N%10) { case 1 : return this->phi1(phi(d)) ; @@ -230,91 +251,6 @@ class CMap3_T : public CMap2_T protected: - /** - * @brief create_pyramid_topo : create a pyramid whose base is n-sided - * @param n, the number of edges of the base - * @return a dart from the base - */ - inline Dart add_pyramid_topo(uint32 n) - { - cgogn_message_assert( n >= 3u ,"The base must have at least 3 edges."); - - std::vector m_tableVertDarts; - m_tableVertDarts.reserve(n); - - // creation of triangles around circumference and storing vertices - for (uint32 i = 0u; i < n; ++i) - m_tableVertDarts.push_back(this->Inherit::Inherit::add_face_topo(3u)); - - // sewing the triangles - for (uint32 i = 0u; i < n-1u; ++i) - { - const Dart d = this->phi_1(m_tableVertDarts[i]); - const Dart e = this->phi1(m_tableVertDarts[i+1]); - this->phi2_sew(d,e); - } - - // sewing the last with the first - this->phi2_sew(this->phi1(m_tableVertDarts[0u]), this->phi_1(m_tableVertDarts[n-1u])); - - // sewing the bottom face - Dart base = this->Inherit::Inherit::add_face_topo(n); - const Dart dres = base; - for(uint32 i = 0u; i < n; ++i) - { - this->phi2_sew(m_tableVertDarts[i], base); - base = this->phi1(base); - } - - // return a dart from the base - return dres; - } - - /** - * @brief create_prism_topo : create a prism whose base is n-sided - * @param n, the number of edges of the base - * @return a dart from the base - */ - Dart add_prism_topo(uint32 n) - { - cgogn_message_assert( n >= 3u ,"The base must have at least 3 edges."); - std::vector m_tableVertDarts; - m_tableVertDarts.reserve(n*2u); - - // creation of quads around circunference and storing vertices - for (uint32 i = 0u; i < n; ++i) - m_tableVertDarts.push_back(this->Inherit::Inherit::add_face_topo(4u)); - - // storing a dart from the vertex pointed by phi1(phi1(d)) - for (uint32 i = 0u; i < n; ++i) - m_tableVertDarts.push_back(this->phi1(this->phi1(m_tableVertDarts[i]))); - - // sewing the quads - for (uint32 i = 0u; i < n-1u; ++i) - { - const Dart d = this->phi_1(m_tableVertDarts[i]); - const Dart e = this->phi1(m_tableVertDarts[i+1u]); - this->phi2_sew(d,e); - } - // sewing the last with the first - this->phi2_sew(this->phi1(m_tableVertDarts[0u]), this->phi_1(m_tableVertDarts[n-1u])); - - // sewing the top & bottom faces - Dart top = this->Inherit::Inherit::add_face_topo(n); - Dart bottom = this->Inherit::Inherit::add_face_topo(n); - const Dart dres = top; - for(uint32 i = 0u; i < n; ++i) - { - this->phi2_sew(m_tableVertDarts[i], top); - this->phi2_sew(m_tableVertDarts[n+i], bottom); - top = this->phi1(top); - bottom = this->phi_1(bottom); - } - - // return a dart from the base - return dres; - } - /** * @brief add_stamp_volume_topo : a flat volume with one face composed of two triangles and another compose of one quad * @return a dart of the quad @@ -414,6 +350,23 @@ class CMap3_T : public CMap2_T return Inherit::has_codegree(Face2(f.dart), codegree); } + /******************************************************************************* + * Boundary information + *******************************************************************************/ + + bool is_adjacent_to_boundary(Boundary c) + { + CGOGN_CHECK_CONCRETE_TYPE; + + bool result = false; + foreach_dart_of_orbit_until(c, [this, &result] (Dart d) + { + if (this->is_boundary(phi3(d))) { result = true; return false; } + return true; + }); + return result; + } + protected: /******************************************************************************* @@ -477,13 +430,47 @@ class CMap3_T : public CMap2_T }); } + template + void foreach_dart_of_PHI1_PHI2_PHI3(Dart d, const FUNC& f) const + { + DartMarkerStore marker(*this); + + std::vector* visited_face2 = cgogn::get_dart_buffers()->get_buffer(); + visited_face2->push_back(d); // Start with the face of d + + // For every face added to the list + for(uint32 i = 0; i < visited_face2->size(); ++i) + { + Dart e = (*visited_face2)[i]; + if (!marker.is_marked(e)) // Face2 has not been visited yet + { + // mark visited darts (current face2) + // and add non visited phi2-adjacent face2 to the list of face2 + Dart it = e; + do + { + f(it); // apply the function to the darts of the face2 + marker.mark(it); // Mark + Dart adj2 = this->phi2(it); // Get phi2-adjacent face2 + if (!marker.is_marked(adj2)) + visited_face2->push_back(adj2); // Add it + it = this->phi1(it); + } while (it != e); + // add phi3-adjacent face2 to the list + visited_face2->push_back(phi3(it)); + } + } + cgogn::get_dart_buffers()->release_buffer(visited_face2); + } + template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21 || - ORBIT == Orbit::PHI1_PHI3 || ORBIT == Orbit::PHI2_PHI3 || ORBIT == Orbit::PHI21_PHI31, + ORBIT == Orbit::PHI1_PHI3 || ORBIT == Orbit::PHI2_PHI3 || + ORBIT == Orbit::PHI21_PHI31 || ORBIT == Orbit::PHI1_PHI2_PHI3, "Orbit not supported in a CMap3"); switch (ORBIT) @@ -496,6 +483,7 @@ class CMap3_T : public CMap2_T case Orbit::PHI2_PHI3: foreach_dart_of_PHI2_PHI3(c.dart, f); break; case Orbit::PHI21: this->foreach_dart_of_PHI21(c.dart, f); break; case Orbit::PHI21_PHI31: foreach_dart_of_PHI21_PHI31(c.dart, f); break; + case Orbit::PHI1_PHI2_PHI3: foreach_dart_of_PHI1_PHI2_PHI3(c.dart, f); break; default: cgogn_assert_not_reached("This orbit is not handled"); break; } } @@ -562,6 +550,43 @@ class CMap3_T : public CMap2_T }); } + template + void foreach_dart_of_PHI1_PHI2_PHI3_until(Dart d, const FUNC& f) const + { + DartMarkerStore marker(*this); + + std::vector* visited_face2 = cgogn::get_dart_buffers()->get_buffer(); + visited_face2->push_back(d); // Start with the face of d + + // For every face added to the list + for(uint32 i = 0; i < visited_face2->size(); ++i) + { + Dart e = (*visited_face2)[i]; + if (!marker.is_marked(e)) // Face2 has not been visited yet + { + // mark visited darts (current face2) + // and add non visited phi2-adjacent face2 to the list of face2 + Dart it = e; + do + { + if (!f(it)) // apply the function to the darts of the face2 + { + cgogn::get_dart_buffers()->release_buffer(visited_face2); + return; + } + marker.mark(it); // Mark + Dart adj2 = this->phi2(it); // Get phi2-adjacent face2 + if (!marker.is_marked(adj2)) + visited_face2->push_back(adj2); // Add it + it = this->phi1(it); + } while (it != e); + // add phi3-adjacent face2 to the list + visited_face2->push_back(phi3(it)); + } + } + cgogn::get_dart_buffers()->release_buffer(visited_face2); + } + template inline void foreach_dart_of_orbit_until(Cell c, const FUNC& f) const { @@ -569,7 +594,8 @@ class CMap3_T : public CMap2_T static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21 || - ORBIT == Orbit::PHI1_PHI3 || ORBIT == Orbit::PHI2_PHI3 || ORBIT == Orbit::PHI21_PHI31, + ORBIT == Orbit::PHI1_PHI3 || ORBIT == Orbit::PHI2_PHI3 || + ORBIT == Orbit::PHI21_PHI31 || ORBIT == Orbit::PHI1_PHI2_PHI3, "Orbit not supported in a CMap3"); switch (ORBIT) @@ -582,6 +608,7 @@ class CMap3_T : public CMap2_T case Orbit::PHI2_PHI3: foreach_dart_of_PHI2_PHI3_until(c.dart, f); break; case Orbit::PHI21: this->foreach_dart_of_PHI21_until(c.dart, f); break; case Orbit::PHI21_PHI31: foreach_dart_of_PHI21_PHI31_until(c.dart, f); break; + case Orbit::PHI1_PHI2_PHI3: foreach_dart_of_PHI1_PHI2_PHI3_until(c.dart, f); break; default: cgogn_assert_not_reached("This orbit is not handled"); break; } } @@ -1086,15 +1113,59 @@ class CMap3_T : public CMap2_T }); } - inline std::pair vertices(Edge e) + inline std::pair vertices(Edge e) + { + return std::pair(Vertex(e.dart), Vertex(this->phi1(e.dart))); + } + +protected: + +#define FOR_ALL_ORBITS( CODE)\ +{static const Orbit orbit_const=DART; CODE }\ +{static const Orbit orbit_const=PHI1; CODE }\ +{static const Orbit orbit_const=PHI2; CODE }\ +{static const Orbit orbit_const=PHI1_PHI2; CODE }\ +{static const Orbit orbit_const=PHI1_PHI3; CODE }\ +{static const Orbit orbit_const=PHI2_PHI3; CODE }\ +{static const Orbit orbit_const=PHI21; CODE }\ +{static const Orbit orbit_const=PHI21_PHI31; CODE }\ +{static const Orbit orbit_const=PHI1_PHI2_PHI3; CODE } + + /** + * @brief check if embedding of map is also embedded in this (create if not). Used by merge method + * @param map + */ + void merge_check_embedding(const Self& map) { - return std::pair(Vertex(e.dart),Vertex(this->phi1(e.dart))); + FOR_ALL_ORBITS + ( + if (!this->template is_embedded() && map.template is_embedded()) + this->template create_embedding(); + ) } - inline std::array verts(Edge e) + /** + * @brief ensure all cells (introduced while merging) are embedded. + * @param first index of first dart to scan + */ + void merge_finish_embedding(uint32 first) { - return {{ Vertex(e.dart),Vertex(this->phi1(e.dart)) }}; + FOR_ALL_ORBITS + ( + if (this->template is_embedded()) + { + for (uint32 j=first; j!= this->topology_.end(); this->topology_.next(j)) + { + if (((orbit_const != Boundary::ORBIT) && (orbit_const != DART)) || (!this->is_boundary(Dart(j)))) + if ((*this->embeddings_[orbit_const])[j] == std::numeric_limits::max()) + this->new_orbit_embedding(Cell(Dart(j))); + } + } + ) } + +#undef FOR_ALL_ORBITS + }; template @@ -1106,7 +1177,7 @@ struct CMap3Type template using CMap3 = CMap3_T>; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP3_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_CORE_MAP_MAP3_CPP_)) extern template class CGOGN_CORE_API CMap3_T>; extern template class CGOGN_CORE_API DartMarker>; extern template class CGOGN_CORE_API DartMarkerStore>; @@ -1119,8 +1190,8 @@ extern template class CGOGN_CORE_API CellMarkerStore, CM extern template class CGOGN_CORE_API CellMarkerStore, CMap3::Edge::ORBIT>; extern template class CGOGN_CORE_API CellMarkerStore, CMap3::Face::ORBIT>; extern template class CGOGN_CORE_API CellMarkerStore, CMap3::Volume::ORBIT>; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP3_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_CORE_MAP_MAP3_CPP_)) } // namespace cgogn -#endif // CORE_CMAP_CMAP3_H_ +#endif // CGOGN_CORE_CMAP_CMAP3_H_ diff --git a/cgogn/core/cmap/cmap3_builder.cpp b/cgogn/core/cmap/cmap3_builder.cpp index 281db1a1..065c7d1f 100644 --- a/cgogn/core/cmap/cmap3_builder.cpp +++ b/cgogn/core/cmap/cmap3_builder.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_CORE_DLL_EXPORT -#define CORE_CMAP_CMAP3_BUILDER_CPP_ +#define CGOGN_CORE_CMAP_CMAP3_BUILDER_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/core/cmap/cmap3_builder.h b/cgogn/core/cmap/cmap3_builder.h index 6008f29b..24fc9a19 100644 --- a/cgogn/core/cmap/cmap3_builder.h +++ b/cgogn/core/cmap/cmap3_builder.h @@ -21,10 +21,10 @@ * * *******************************************************************************/ -#ifndef CORE_CMAP_CMAP3_BUILDER_H_ -#define CORE_CMAP_CMAP3_BUILDER_H_ +#ifndef CGOGN_CORE_CMAP_CMAP3_BUILDER_H_ +#define CGOGN_CORE_CMAP_CMAP3_BUILDER_H_ -#include +#include namespace cgogn { @@ -49,7 +49,6 @@ class CMap3Builder_T template using ChunkArrayContainer = typename CMap3::template ChunkArrayContainer; - inline CMap3Builder_T(CMap3& map) : map_(map) {} @@ -126,6 +125,26 @@ class CMap3Builder_T map_.template set_embedding(d, emb); } + /** + * @brief sew two volumes along a face + * The darts given in the Volume parameters must be part of Face2 that have + * a similar co-degree and whose darts are all phi3 fix points + * @param v1 first volume + * @param v2 second volume + */ + inline void sew_volumes(Volume v1, Volume v2) + { + Dart it1 = v1.dart; + Dart it2 = v2.dart; + const Dart begin = it1; + do + { + phi3_sew(it1, it2); + it1 = map_.phi1(it1); + it2 = map_.phi_1(it2); + } while (it1 != begin); + } + inline void close_hole_topo(Dart d) { cgogn_message_assert(map_.phi3(d) == d, "CMap3: close hole called on a dart that is not a phi3 fix point"); @@ -207,7 +226,7 @@ class CMap3Builder_T close_hole_topo(d); map_.foreach_dart_of_orbit(Volume(map_.phi3(d)), [&] (Dart db) { - map_.set_boundary(db,true); + map_.set_boundary(db, true); }); const Volume new_volume(map_.phi3(d)); @@ -282,13 +301,13 @@ class CMap3Builder_T CMap3& map_; }; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_CMAP_CMAP3_BUILDER_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_CORE_CMAP_CMAP3_BUILDER_CPP_)) extern template class CGOGN_CORE_API cgogn::CMap3Builder_T; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_CMAP_CMAP3_BUILDER_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_CORE_CMAP_CMAP3_BUILDER_CPP_)) using CMap3Builder = cgogn::CMap3Builder_T; } // namespace cgogn -#endif // CORE_CMAP_CMAP3_BUILDER_H_ +#endif // CGOGN_CORE_CMAP_CMAP3_BUILDER_H_ diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 3d3c0ac9..24345a7b 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -21,23 +21,23 @@ * * *******************************************************************************/ -#ifndef CORE_CMAP_MAP_BASE_H_ -#define CORE_CMAP_MAP_BASE_H_ +#ifndef CGOGN_CORE_CMAP_MAP_BASE_H_ +#define CGOGN_CORE_CMAP_MAP_BASE_H_ #include #include -#include -#include +#include +#include +#include -#include -#include -#include +#include +#include +#include + +#include +#include -#include -#include -#include -#include namespace cgogn { @@ -63,10 +63,11 @@ class MapBase : public MapBaseData using typename Inherit::ChunkArrayGen; template using ChunkArray = typename Inherit::template ChunkArray; + using typename Inherit::ChunkArrayBool; - using AttributeHandlerGen = cgogn::AttributeHandlerGen; + using AttributeGen = cgogn::AttributeGen; template - using AttributeHandler = cgogn::AttributeHandler; + using Attribute = cgogn::Attribute; using ConcreteMap = typename MAP_TYPE::TYPE; @@ -150,6 +151,12 @@ class MapBase : public MapBaseData * Container elements management *******************************************************************************/ + /** + * \brief Adds a topological element of PRIM_SIZE to the topology container + * \return the index of the added element + * Adding a topological element consists in adding PRIM_SIZE lines + * to the topological container starting from index + */ inline uint32 add_topology_element() { const uint32 idx = this->topology_.template insert_lines(); @@ -157,19 +164,33 @@ class MapBase : public MapBaseData for (uint32 orbit = 0u; orbit < NB_ORBITS; ++orbit) { if (this->embeddings_[orbit]) - (*this->embeddings_[orbit])[idx] = EMBNULL; + (*this->embeddings_[orbit])[idx] = INVALID_INDEX; } return idx; } +// template +// inline void compact_orbit_container() +// { +// if (!this->template is_embedded()) +// return; + +// auto& cac = this->template get_attribute_container(); +// const std::vector& map_old_new = cac.template compact(); +// this->parallel_foreach_dart([&map_old_new,this](Dart d, uint32) +// { +// uint32& old_idx = this->embeddings_[ORBIT]->operator[](d); +// const uint32 new_idx = map_old_new[old_idx]; +// if (new_idx != UINT32_MAX) +// old_idx = new_idx; +// }); +// } + /** - * \brief Removes a topological element of PRIM_SIZE - * from the topology container - * \details Removing a topological element consists in - * removing PRIM_SIZE lines of the topological container starting - * from index - * - * \param int [description] + * \brief Removes a topological element of PRIM_SIZE from the topology container + * \param index the index of the element to remove + * Removing a topological element consists in removing PRIM_SIZE lines + * of the topological container starting from index */ inline void remove_topology_element(uint32 index) { @@ -180,7 +201,7 @@ class MapBase : public MapBaseData if(this->embeddings_[orbit]) { uint32 emb = (*this->embeddings_[orbit])[index]; - if (emb != EMBNULL) + if (emb != INVALID_INDEX) this->attributes_[orbit].unref_line(emb); } } @@ -216,14 +237,13 @@ class MapBase : public MapBaseData * @return a handler to the created attribute */ template - inline AttributeHandler add_attribute(const std::string& attribute_name = "") + inline Attribute add_attribute(const std::string& attribute_name = "") { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - if (!this->template is_embedded()) create_embedding(); ChunkArray* ca = this->attributes_[ORBIT].template add_attribute(attribute_name); - return AttributeHandler(this, ca); + return Attribute(this, ca); } /** @@ -232,7 +252,7 @@ class MapBase : public MapBaseData * @return true if remove succeed else false */ template - inline bool remove_attribute(AttributeHandler& ah) + inline bool remove_attribute(Attribute& ah) { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); @@ -243,30 +263,53 @@ class MapBase : public MapBaseData /** * \brief search an attribute for a given orbit * @param attribute_name attribute name - * @return an AttributeHandler + * @return an Attribute */ template - inline AttributeHandler get_attribute(const std::string& attribute_name) + inline Attribute get_attribute(const std::string& attribute_name) { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); ChunkArray* ca = this->attributes_[ORBIT].template get_attribute(attribute_name); - return AttributeHandler(this, ca); + return Attribute(this, ca); } /** * \brief search an attribute for a given orbit and change its type (if size is compatible). First template arg is asked type, second is real type. * @param attribute_name attribute name - * @return an AttributeHandler + * @return an Attribute */ template - inline AttributeHandler get_attribute_force_type(const std::string& attribute_name) + inline Attribute get_attribute_force_type(const std::string& attribute_name) { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); static_assert(sizeof(T_ASK) == sizeof(T_ATT), "Incompatible casting operation between attributes, sizes are differents"); ChunkArray* ca = reinterpret_cast*>(this->attributes_[ORBIT].template get_attribute(attribute_name)); - return AttributeHandler(this, ca); + return Attribute(this, ca); + } + + + template + inline void swap_attributes(Attribute& ah1, Attribute& ah2) + { + static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); + + cgogn_message_assert(ah1.is_linked_to(this), "swap_attributes: wrong map"); + cgogn_message_assert(ah2.is_linked_to(this), "swap_attributes: wrong map"); + + this->attributes_[ORBIT].swap_data_attributes(ah1.get_data(), ah2.get_data()); + } + + template + inline void copy_attribute(Attribute& dest, Attribute& src) + { + static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); + + cgogn_message_assert(dest.is_linked_to(this), "copy_attribute: wrong map"); + cgogn_message_assert(src.is_linked_to(this), "copy_attribute: wrong map"); + + this->attributes_[ORBIT].copy_data_attribute(dest.get_data(), src.get_data()); } protected: @@ -280,14 +323,14 @@ class MapBase : public MapBaseData * @return a mark attribute on the topology container */ template - inline ChunkArray* get_mark_attribute() + inline ChunkArrayBool* get_mark_attribute() { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); std::size_t thread = this->get_current_thread_index(); if (!this->mark_attributes_[ORBIT][thread].empty()) { - ChunkArray* ca = this->mark_attributes_[ORBIT][thread].back(); + ChunkArrayBool* ca = this->mark_attributes_[ORBIT][thread].back(); this->mark_attributes_[ORBIT][thread].pop_back(); return ca; } @@ -296,7 +339,7 @@ class MapBase : public MapBaseData std::lock_guard lock(this->mark_attributes_mutex_[ORBIT]); if (!this->template is_embedded()) create_embedding(); - ChunkArray* ca = this->attributes_[ORBIT].add_marker_attribute(); + ChunkArrayBool* ca = this->attributes_[ORBIT].add_marker_attribute(); return ca; } } @@ -306,7 +349,7 @@ class MapBase : public MapBaseData * @param the mark attribute to release */ template - inline void release_mark_attribute(ChunkArray* ca) + inline void release_mark_attribute(ChunkArrayBool* ca) { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(this->template is_embedded(), "Invalid parameter: orbit not embedded"); @@ -334,8 +377,8 @@ class MapBase : public MapBaseData ChunkArray* ca = this->topology_.template add_attribute(oss.str()); this->embeddings_[ORBIT] = ca; - // initialize all darts indices to EMBNULL for this ORBIT - foreach_dart([ca] (Dart d) { (*ca)[d.index] = EMBNULL; }); + // initialize all darts indices to INVALID_INDEX for this ORBIT + foreach_dart([ca] (Dart d) { (*ca)[d.index] = INVALID_INDEX; }); // initialize the indices of the existing orbits foreach_cell([this] (Cell c) { this->new_orbit_embedding(c); }); @@ -367,7 +410,7 @@ class MapBase : public MapBaseData static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(this->template is_embedded(), "Invalid parameter: orbit not embedded"); - AttributeHandler counter = add_attribute("__tmp_counter"); + Attribute counter = add_attribute("__tmp_counter"); for (uint32& i : counter) i = 0; foreach_cell([this, &counter] (Cell c) @@ -402,7 +445,7 @@ class MapBase : public MapBaseData cgogn_message_assert(this->template is_embedded(), "Invalid parameter: orbit not embedded"); const ConcreteMap* cmap = to_concrete(); - AttributeHandler, ORBIT> counter = add_attribute, ORBIT>("__tmp_dart_per_emb"); + Attribute, ORBIT> counter = add_attribute, ORBIT>("__tmp_dart_per_emb"); bool result = true; const typename Inherit::template ChunkArrayContainer& container = this->attributes_[ORBIT]; @@ -412,14 +455,14 @@ class MapBase : public MapBaseData { const uint32 idx = this->get_embedding(c); // check used indices are valid - if (idx == EMBNULL) + if (idx == INVALID_INDEX) { result = false; - cgogn_log_error("is_well_embedded") << "EMBNULL found for dart " << c << " in orbit " << orbit_name(ORBIT); + cgogn_log_error("is_well_embedded") << "INVALID_INDEX found for dart " << c << " in orbit " << orbit_name(ORBIT); return; } counter[idx].push_back(c); - // check all darts of the cell use the same index (distinct to EMBNULL) + // check all darts of the cell use the same index (distinct to INVALID_INDEX) cmap->foreach_dart_of_orbit(c, [&] (Dart d) { const uint32 emb_d = this->get_embedding(CellType(d)); @@ -481,17 +524,15 @@ class MapBase : public MapBaseData *******************************************************************************/ /** - * \brief return true if c1 and c2 represent the same cell, i.e. contain darts of the same orbit + * \brief return true if c1 and c2 represent the same cell + * Comparison is done using exclusively the topological information (darts) * @tparam ORBIT considered orbit * @param c1 first cell to compare * @param c2 second cell to compare */ template - bool same_cell(Cell c1, Cell c2) const + bool same_orbit(Cell c1, Cell c2) const { - if (this->template is_embedded()) - return this->get_embedding(c1) == this->get_embedding(c2); - bool result = false; to_concrete()->foreach_dart_of_orbit_until(c1, [&] (Dart d) -> bool { @@ -505,6 +546,22 @@ class MapBase : public MapBaseData return result; } + /** + * \brief return true if c1 and c2 represent the same cell + * If the orbit is embedded, the comparison is done on the indices, otherwise it is done using the darts + * @tparam ORBIT considered orbit + * @param c1 first cell to compare + * @param c2 second cell to compare + */ + template + bool same_cell(Cell c1, Cell c2) const + { + if (this->template is_embedded()) + return this->get_embedding(c1) == this->get_embedding(c2); + else + return same_orbit(c1, c2); + } + /** * \brief return the number of darts in the map * @return @@ -538,6 +595,14 @@ class MapBase : public MapBaseData return result; } + /** + * \brief return the number of connected components of the map + */ + uint32 nb_connected_components() const + { + return nb_cells(); + } + /** * \brief return the number of darts in the given cell */ @@ -559,6 +624,32 @@ class MapBase : public MapBaseData this->boundary_marker_->set_value(d.index, b); } + template + bool is_incident_to_boundary(Cell c) const + { + static_assert(!std::is_same, typename ConcreteMap::Boundary>::value, "is_incident_to_boundary is not defined for boundary cells"); + bool result = false; + to_concrete()->foreach_dart_of_orbit_until(c, [this, &result] (Dart d) + { + if (is_boundary(d)) { result = true; return false; } + return true; + }); + return result; + } + + template + Dart get_boundary_dart(Cell c) const + { + static_assert(!std::is_same, typename ConcreteMap::Boundary>::value, "get_boundary_dart is not defined for boundary cells"); + Dart result; + to_concrete()->foreach_dart_of_orbit_until(c, [this, &result] (Dart d) + { + if (is_boundary(d)) { result = d; return false; } + return true; + }); + return result; + } + /******************************************************************************* * Traversals *******************************************************************************/ @@ -669,10 +760,8 @@ class MapBase : public MapBaseData protected: /*! - * \Brief Methods to iterate over darts with a MASK that filters the traversed darts. - * A MASK is a callable that determines if a dart should be traversed or skipped. - * It returns false when a dart should be skipped, true in other cases. - * These functions also skip boundary darts. + * \Brief Methods to iterate over darts. + * These functions skip boundary darts. */ inline Dart begin() const { @@ -723,18 +812,24 @@ class MapBase : public MapBaseData parallel_foreach_cell(f, [] (CellType) { return true; }); } + template + inline void foreach_cell_until(const FUNC& f) const + { + foreach_cell_until(f, [] (Dart) { return true; }); + } + /** * \brief apply a function on each cell of the map (boundary cells excluded) - * that is selected by the given MASK function (MASK : CellType -> bool) + * that is selected by the given FilterFunction (CellType -> bool) * (the dimension of the traversed cells is determined based on the parameter of the given callable) * @tparam FUNC type of the callable * @param f a callable */ template ::type* = nullptr> - inline void foreach_cell(const FUNC& f, const MASK& mask) const + typename FilterFunction, + typename std::enable_if::type* = nullptr> + inline void foreach_cell(const FUNC& f, const FilterFunction& filter) const { using CellType = func_parameter_type(FUNC); static const Orbit ORBIT = CellType::ORBIT; @@ -742,25 +837,25 @@ class MapBase : public MapBaseData switch (STRATEGY) { case FORCE_DART_MARKING : - foreach_cell_dart_marking(f, mask); + foreach_cell_dart_marking(f, filter); break; case FORCE_CELL_MARKING : - foreach_cell_cell_marking(f, mask); + foreach_cell_cell_marking(f, filter); break; case AUTO : if (this->template is_embedded()) - foreach_cell_cell_marking(f, mask); + foreach_cell_cell_marking(f, filter); else - foreach_cell_dart_marking(f, mask); + foreach_cell_dart_marking(f, filter); break; } } template ::type* = nullptr> - inline void parallel_foreach_cell(const FUNC& f, const MASK& mask) const + typename FilterFunction, + typename std::enable_if::type* = nullptr> + inline void parallel_foreach_cell(const FUNC& f, const FilterFunction& filter) const { static_assert(check_func_ith_parameter_type(FUNC, 1, uint32), "Wrong function second parameter type"); @@ -770,42 +865,106 @@ class MapBase : public MapBaseData switch (STRATEGY) { case FORCE_DART_MARKING : - parallel_foreach_cell_dart_marking(f, mask); + parallel_foreach_cell_dart_marking(f, filter); + break; + case FORCE_CELL_MARKING : + parallel_foreach_cell_cell_marking(f, filter); + break; + case AUTO : + if (this->template is_embedded()) + parallel_foreach_cell_cell_marking(f, filter); + else + parallel_foreach_cell_dart_marking(f, filter); + break; + } + } + + template ::type* = nullptr> + void foreach_cell_until(const FUNC& f, const FilterFunction& filter) const + { + using CellType = func_parameter_type(FUNC); + + switch (STRATEGY) + { + case FORCE_DART_MARKING : + foreach_cell_until_dart_marking(f, filter); break; case FORCE_CELL_MARKING : - parallel_foreach_cell_cell_marking(f, mask); + foreach_cell_until_cell_marking(f, filter); break; case AUTO : if (this->template is_embedded()) - parallel_foreach_cell_cell_marking(f, mask); + foreach_cell_until_cell_marking(f, filter); else - parallel_foreach_cell_dart_marking(f, mask); + foreach_cell_until_dart_marking(f, filter); break; } } /** - * \brief apply a function on each cell of the map that is provided by the given MASK object + * \brief apply a function on each cell of the map (boundary cells excluded) + * that is selected by the filter function of the corresponding CellType within the given Filters object * (the dimension of the traversed cells is determined based on the parameter of the given callable) * @tparam FUNC type of the callable * @param f a callable */ template , MASK>::value>::type* = nullptr> - inline void foreach_cell(const FUNC& f, const MASK& mask) const + typename Filters, + typename std::enable_if::value>::type* = nullptr> + inline void foreach_cell(const FUNC& f, const Filters& filters) const { using CellType = func_parameter_type(FUNC); - for (CellType it = mask.begin(); !mask.end(); it = mask.next()) - f(it); + foreach_cell(f, [&filters] (CellType c) { return filters.filter(c); }); + } + + template ::value>::type* = nullptr> + inline void parallel_foreach_cell(const FUNC& f, const Filters& filters) const + { + using CellType = func_parameter_type(FUNC); + + parallel_foreach_cell(f, [&filters] (CellType c) { return filters.filter(c); }); + } + + template ::value>::type* = nullptr> + inline void foreach_cell_until(const FUNC& f, const Filters& filters) const + { + using CellType = func_parameter_type(FUNC); + + foreach_cell_until(f, [&filters] (CellType c) { return filters.filter(c); }); + } + + /** + * \brief apply a function on each cell of the map that is provided by the given Traversor object + * (the dimension of the traversed cells is determined based on the parameter of the given callable) + * @tparam FUNC type of the callable + * @param f a callable + */ + template ::value>::type* = nullptr> + inline void foreach_cell(const FUNC& f, const Traversor& t) const + { + using CellType = func_parameter_type(FUNC); + + for(typename Traversor::const_iterator it = t.template begin(), end = t.template end() ; it != end; ++it) + f(CellType(*it)); } template , MASK>::value>::type* = nullptr> - inline void parallel_foreach_cell(const FUNC& f, const MASK& mask) const + typename Traversor, + typename std::enable_if::value>::type* = nullptr> + inline void parallel_foreach_cell(const FUNC& f, const Traversor& t) const { + static_assert(check_func_ith_parameter_type(FUNC, 1, uint32), "Wrong function second parameter type"); + using CellType = func_parameter_type(FUNC); using VecCell = std::vector; @@ -823,21 +982,20 @@ class MapBase : public MapBaseData Buffers* dbuffs = cgogn::get_dart_buffers(); - CellType it = mask.begin(); - uint32 i = 0u; // buffer id (0/1) uint32 j = 0u; // thread id (0..nb_threads_pool) - while (!mask.end()) + auto it = t.template begin(); + const auto it_end = t.template end(); + while(it != it_end) { // fill buffer cells_buffers[i].push_back(dbuffs->template get_cell_buffer()); VecCell& cells = *cells_buffers[i].back(); cells.reserve(PARALLEL_BUFFER_SIZE); - for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && !mask.end(); ++k) + for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && (it != it_end); ++k) { - CellType c(it); - cells.push_back(c); - it = mask.next(); + cells.push_back(CellType(*it)); + ++it; } // launch thread futures[i].push_back(thread_pool->enqueue([&cells, &f] (uint32 th_id) @@ -870,93 +1028,41 @@ class MapBase : public MapBaseData dbuffs->release_cell_buffer(b); } - /** - * \brief apply a function on each cell of the map (boundary cells excluded) - * and stops when the function returns false - * (the dimension of the traversed cells is determined based on the parameter of the given callable) - * @tparam FUNC type of the callable - * @param f a callable - */ - template - inline void foreach_cell_until(const FUNC& f) const - { - foreach_cell_until(f, [] (Dart) { return true; }); - } - - /** - * \brief apply a function on each cell of the map (boundary cells excluded) - * that is selected by the given MASK function (MASK : CellType -> bool) - * and stops when the function returns false - * (the dimension of the traversed cells is determined based on the parameter of the given callable) - * @tparam FUNC type of the callable - * @param f a callable - */ - template ::type* = nullptr> - void foreach_cell_until(const FUNC& f, const MASK& mask) const - { - using CellType = func_parameter_type(FUNC); - - switch (STRATEGY) - { - case FORCE_DART_MARKING : - foreach_cell_until_dart_marking(f, mask); - break; - case FORCE_CELL_MARKING : - foreach_cell_until_cell_marking(f, mask); - break; - case AUTO : - if (this->template is_embedded()) - foreach_cell_until_cell_marking(f, mask); - else - foreach_cell_until_dart_marking(f, mask); - break; - } - } - - /** - * \brief apply a function on each cell of the map (boundary cells excluded) - * that is provided by the given MASK object and stops when the function returns false - * (the dimension of the traversed cells is determined based on the parameter of the given callable) - * @tparam FUNC type of the callable - * @param f a callable - */ template , MASK>::value>::type* = nullptr> - inline void foreach_cell_until(const FUNC& f, const MASK& mask) const + typename Traversor, + typename std::enable_if::value>::type* = nullptr> + inline void foreach_cell_until(const FUNC& f, const Traversor& t) const { - using CellType = typename function_traits::template arg<0>::type; + using CellType = func_parameter_type(FUNC); - for (CellType it = mask.begin(); !mask.end(); it = mask.next()) - if (!f(it)) + for(typename Traversor::const_iterator it = t.template begin(), end = t.template end() ;it != end; ++it) + if (!f(CellType(*it))) break; } protected: - template - inline void foreach_cell_dart_marking(const FUNC& f, const MASK& mask) const + template + inline void foreach_cell_dart_marking(const FUNC& f, const FilterFunction& filter) const { using CellType = func_parameter_type(FUNC); - DartMarker dm(*to_concrete()); - for (Dart it = begin(), last = end(); it.index < last.index; next(it)) + const ConcreteMap* cmap = to_concrete(); + DartMarker dm(*cmap); + for (Dart it = cmap->begin(), last = cmap->end(); it.index < last.index; cmap->next(it)) { if (!dm.is_marked(it)) { CellType c(it); dm.mark_orbit(c); - if (mask(c)) + if (filter(c)) f(c); } } } - template - inline void parallel_foreach_cell_dart_marking(const FUNC& f, const MASK& mask) const + template + inline void parallel_foreach_cell_dart_marking(const FUNC& f, const FilterFunction& filter) const { using CellType = func_parameter_type(FUNC); @@ -975,9 +1081,10 @@ class MapBase : public MapBaseData Buffers* dbuffs = cgogn::get_dart_buffers(); - DartMarker dm(*to_concrete()); - Dart it = begin(); - Dart last = end(); + const ConcreteMap* cmap = to_concrete(); + DartMarker dm(*cmap); + Dart it = cmap->begin(); + Dart last = cmap->end(); uint32 i = 0u; // buffer id (0/1) uint32 j = 0u; // thread id (0..nb_threads_pool) @@ -993,13 +1100,13 @@ class MapBase : public MapBaseData { CellType c(it); dm.mark_orbit(c); - if (mask(c)) + if (filter(c)) { cells.push_back(c); ++k; } } - next(it); + cmap->next(it); } //launch thread futures[i].push_back(thread_pool->enqueue([&cells, &f] (uint32 th_id) @@ -1032,27 +1139,28 @@ class MapBase : public MapBaseData dbuffs->release_cell_buffer(b); } - template - inline void foreach_cell_cell_marking(const FUNC& f, const MASK& mask) const + template + inline void foreach_cell_cell_marking(const FUNC& f, const FilterFunction& filter) const { using CellType = func_parameter_type(FUNC); static const Orbit ORBIT = CellType::ORBIT; - CellMarker cm(*to_concrete()); - for (Dart it = begin(), last = end(); it.index < last.index; next(it)) + const ConcreteMap* cmap = to_concrete(); + CellMarker cm(*cmap); + for (Dart it = cmap->begin(), last = cmap->end(); it.index < last.index; cmap->next(it)) { CellType c(it); if (!cm.is_marked(c)) { cm.mark(c); - if (mask(c)) + if (filter(c)) f(c); } } } - template - inline void parallel_foreach_cell_cell_marking(const FUNC& f, const MASK& mask) const + template + inline void parallel_foreach_cell_cell_marking(const FUNC& f, const FilterFunction& filter) const { using CellType = func_parameter_type(FUNC); static const Orbit ORBIT = CellType::ORBIT; @@ -1072,9 +1180,10 @@ class MapBase : public MapBaseData Buffers* dbuffs = cgogn::get_dart_buffers(); - CellMarker cm(*to_concrete()); - Dart it = begin(); - Dart last = end(); + const ConcreteMap* cmap = to_concrete(); + CellMarker cm(*cmap); + Dart it = cmap->begin(); + Dart last = cmap->end(); uint32 i = 0u; // buffer id (0/1) uint32 j = 0u; // thread id (0..nb_threads_pool) @@ -1090,13 +1199,13 @@ class MapBase : public MapBaseData if (!cm.is_marked(c)) { cm.mark(c); - if (mask(c)) + if (filter(c)) { cells.push_back(c); ++k; } } - next(it); + cmap->next(it); } // launch thread futures[i].push_back(thread_pool->enqueue([&cells, &f] (uint32 th_id) @@ -1129,46 +1238,200 @@ class MapBase : public MapBaseData dbuffs->release_cell_buffer(b); } - template - inline void foreach_cell_until_dart_marking(const FUNC& f, const MASK& mask) const + template + inline void foreach_cell_until_dart_marking(const FUNC& f, const FilterFunction& filter) const { using CellType = func_parameter_type(FUNC); - DartMarker dm(*to_concrete()); - for (Dart it = begin(), last = end(); it.index < last.index; next(it)) + const ConcreteMap* cmap = to_concrete(); + DartMarker dm(*cmap); + for (Dart it = cmap->begin(), last = cmap->end(); it.index < last.index; cmap->next(it)) { if (!dm.is_marked(it)) { CellType c(it); dm.mark_orbit(c); - if(mask(c)) + if(filter(c)) if(!f(c)) break; } } } - template - inline void foreach_cell_until_cell_marking(const FUNC& f, const MASK& mask) const + template + inline void foreach_cell_until_cell_marking(const FUNC& f, const FilterFunction& filter) const { using CellType = func_parameter_type(FUNC); static const Orbit ORBIT = CellType::ORBIT; - CellMarker cm(*to_concrete()); - for (Dart it = begin(), last = end(); it.index < last.index; next(it)) + const ConcreteMap* cmap = to_concrete(); + CellMarker cm(*cmap); + for (Dart it = cmap->begin(), last = cmap->end(); it.index < last.index; cmap->next(it)) { CellType c(it); if (!cm.is_marked(c)) { cm.mark(c); - if(mask(c)) + if(filter(c)) if(!f(c)) break; } } } + + +public: + + /******************************************************************************* + * compacting + *******************************************************************************/ + /** + * @brief compact an embedding orbit + * @param orbit to compact + */ + void compact_embedding(uint32 orbit) + { + ChunkArray* embedding = this->embeddings_[orbit]; + if (embedding != nullptr) + { + std::vector old_new = this->attributes_[orbit].template compact<1>(); + if (!old_new.empty()) + { + for (uint32 i=this->topology_.begin(); i!= this->topology_.end(); this->topology_.next(i)) + { + uint32& emb = (*embedding)[i]; + if ((emb != std::numeric_limits::max()) + && (old_new[emb] != std::numeric_limits::max())) + emb = old_new[emb]; + } + } + } + } + + void compact_topo() + { + std::vector old_new = this->topology_.template compact(); + + if (old_new.empty()) + return; // already compact nothing to do with relationss + + for (ChunkArrayGen* ptr: this->topology_.get_attributes()) + { + ChunkArray* ca = dynamic_cast*>(ptr); + if (ca) + { + for (uint32 i=this->topology_.begin(); i!= this->topology_.end(); this->topology_.next(i)) + { + Dart& d = (*ca)[i]; + uint32 idx = d.index; + if (old_new[idx] != std::numeric_limits::max()) + d = Dart(old_new[idx]); + } + } + } + } + + /** + * @brief compact this map + */ + void compact() + { + compact_topo(); + + for (uint32 orb=0; orbembeddings_[i] != nullptr) + { + if (!this->attributes_[i].check_before_merge(map.attributes_[i])) + return false; + } + } + + // compact and store index of copied darts + this->compact_topo(); + uint32 first = this->topology_.size(); + + // + ConcreteMap* concrete = to_concrete(); + concrete->merge_check_embedding(map); + std::vector old_new_topo = this->topology_.template merge(map.topology_); + + // change topo relations of copied darts + for (ChunkArrayGen* ptr: this->topology_.get_attributes()) + { + ChunkArray* cad = dynamic_cast*>(ptr); + if (cad) + { + for (uint32 i=first; i!= this->topology_.end(); this->topology_.next(i)) + { + Dart& d = (*cad)[i]; + uint32 idx = d.index; + if (old_new_topo[idx] != INVALID_INDEX) + d = Dart(old_new_topo[idx]); + } + } + } + + // set boundary of copied darts + map.foreach_dart([&] (Dart d) + { + if (map.is_boundary(d)) + { + Dart dd = Dart(old_new_topo[d.index]); + this->set_boundary(dd,true); + } + }); + + // change embedding indices of moved lines + for(uint32 i=0; i* emb = this->embeddings_[i]; + if (emb != nullptr) + { + if (map.embeddings_[i] == nullptr) //set embedding to INVALID for further easy detection + { + for (uint32 j=first; j!= this->topology_.end(); this->topology_.next(j)) + (*emb)[j] = INVALID_INDEX; + } + else + { + std::vector old_new = this->attributes_[i].template merge<1>(map.attributes_[i]); + for (uint32 j=first; j!= this->topology_.end(); this->topology_.next(j)) + { + uint32& e = (*emb)[j]; + if (e != INVALID_INDEX) + { + if (old_new[e] != INVALID_INDEX) + e = old_new[e]; + } + } + } + } + } + + // embed remaining cells + concrete->merge_finish_embedding(first); + + // ok + return true; + } + }; } // namespace cgogn -#endif // CORE_CMAP_MAP_BASE_H_ +#endif // CGOGN_CORE_CMAP_MAP_BASE_H_ diff --git a/cgogn/core/cmap/map_base_data.cpp b/cgogn/core/cmap/map_base_data.cpp index 02facbfb..281f0788 100644 --- a/cgogn/core/cmap/map_base_data.cpp +++ b/cgogn/core/cmap/map_base_data.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_CORE_DLL_EXPORT -#define CORE_MAP_MAP_BASE_DATA_CPP_ +#define CGOGN_CORE_MAP_MAP_BASE_DATA_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index 96d066fb..e362e914 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -21,8 +21,8 @@ * * *******************************************************************************/ -#ifndef CORE_CMAP_MAP_BASE_DATA_H_ -#define CORE_CMAP_MAP_BASE_DATA_H_ +#ifndef CGOGN_CORE_CMAP_MAP_BASE_DATA_H_ +#define CGOGN_CORE_CMAP_MAP_BASE_DATA_H_ #include #include @@ -31,13 +31,13 @@ #include #include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #define CGOGN_CHECK_DYNAMIC_TYPE cgogn_message_assert( (std::is_same::value),\ std::string("dynamic type of current object : ") + cgogn::internal::demangle(std::string(typeid(*this).name())) + std::string(",\nwhereas Self = ") + cgogn::name_of_type(Self())) @@ -78,9 +78,9 @@ class CGOGN_CORE_API MapGen } }; -// forward declaration of class AttributeHandlerOrbit +// forward declaration of class AttributeOrbit template -class AttributeHandlerOrbit; +class AttributeOrbit; /** * @brief The MapBaseData class @@ -95,19 +95,20 @@ class MapBaseData : public MapGen static const uint32 CHUNKSIZE = MAP_TRAITS::CHUNK_SIZE; static const uint32 NB_UNKNOWN_THREADS = 4u; - template friend class AttributeHandlerOrbit; - template friend class AttributeHandler; + template friend class AttributeOrbit; + template friend class Attribute; template using ChunkArrayContainer = cgogn::ChunkArrayContainer; using ChunkArrayGen = cgogn::ChunkArrayGen; template using ChunkArray = cgogn::ChunkArray; + using ChunkArrayBool = cgogn::ChunkArrayBool; protected: // topology & embedding indices - ChunkArrayContainer topology_; + ChunkArrayContainer topology_; /// per orbit attributes std::array, NB_ORBITS> attributes_; @@ -116,14 +117,14 @@ class MapBaseData : public MapGen std::array*, NB_ORBITS> embeddings_; /// boundary marker shortcut - ChunkArray* boundary_marker_; + ChunkArrayBool* boundary_marker_; /// vector of available mark attributes per thread on the topology container - std::vector*>> mark_attributes_topology_; + std::vector> mark_attributes_topology_; std::mutex mark_attributes_topology_mutex_; /// vector of available mark attributes per orbit per thread on attributes containers - std::array*>>, NB_ORBITS> mark_attributes_; + std::array>, NB_ORBITS> mark_attributes_; std::array mark_attributes_mutex_; /// Before accessing the map, a thread should call map.add_thread(std::this_thread::get_id()) (and do a map.remove_thread(std::this_thread::get_id() before it terminates) @@ -177,12 +178,17 @@ class MapBaseData : public MapGen *******************************************************************************/ template - inline const ChunkArrayContainer& get_attribute_container() const + inline const ChunkArrayContainer& get_const_attribute_container() const { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); return attributes_[ORBIT]; } + inline const ChunkArrayContainer& get_topology_container() const + { + return topology_; + } + protected: template @@ -200,19 +206,19 @@ class MapBaseData : public MapGen * \brief get a mark attribute on the topology container (from pool or created) * @return a mark attribute on the topology container */ - inline ChunkArray* get_topology_mark_attribute() + inline ChunkArrayBool* get_topology_mark_attribute() { std::size_t thread = this->get_current_thread_index(); if (!this->mark_attributes_topology_[thread].empty()) { - ChunkArray* ca = this->mark_attributes_topology_[thread].back(); + ChunkArrayBool* ca = this->mark_attributes_topology_[thread].back(); this->mark_attributes_topology_[thread].pop_back(); return ca; } else { std::lock_guard lock(this->mark_attributes_topology_mutex_); - ChunkArray* ca = this->topology_.add_marker_attribute(); + ChunkArrayBool* ca = this->topology_.add_marker_attribute(); return ca; } } @@ -221,7 +227,7 @@ class MapBaseData : public MapGen * \brief release a mark attribute on the topology container * @param the mark attribute to release */ - inline void release_topology_mark_attribute(ChunkArray* ca) + inline void release_topology_mark_attribute(ChunkArrayBool* ca) { std::size_t thread = this->get_current_thread_index(); this->mark_attributes_topology_[thread].push_back(ca); @@ -251,7 +257,7 @@ class MapBaseData : public MapGen { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(is_embedded(), "Invalid parameter: orbit not embedded"); - cgogn_message_assert((*embeddings_[ORBIT])[c.dart.index] != EMBNULL, "get_embedding result is EMBNULL"); + cgogn_message_assert((*embeddings_[ORBIT])[c.dart.index] != INVALID_INDEX, "get_embedding result is INVALID_INDEX"); return (*embeddings_[ORBIT])[c.dart.index]; } @@ -264,14 +270,14 @@ class MapBaseData : public MapGen static const Orbit ORBIT = CellType::ORBIT; static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(is_embedded(), "Invalid parameter: orbit not embedded"); - cgogn_message_assert(emb != EMBNULL,"cannot set an embedding to EMBNULL."); + cgogn_message_assert(emb != INVALID_INDEX,"cannot set an embedding to INVALID_INDEX."); const uint32 old = (*embeddings_[ORBIT])[d.index]; // ref_line() is done before unref_line() to avoid deleting the indexed line if old == emb attributes_[ORBIT].ref_line(emb); // ref the new emb - if (old != EMBNULL) - attributes_[ORBIT].unref_line(old); // unref the old emb + if (old != INVALID_INDEX) + attributes_[ORBIT].unref_line(old); // unref the old emb (*embeddings_[ORBIT])[d.index] = emb; // affect the embedding to the dart } @@ -349,12 +355,14 @@ class MapBaseData : public MapGen if (it == thread_ids_.end() || *it != thread_id) thread_ids_.insert(it, thread_id); } + + }; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP_BASE_DATA_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_CORE_MAP_MAP_BASE_DATA_CPP_)) extern template class CGOGN_CORE_API MapBaseData; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP_BASE_DATA_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_CORE_MAP_MAP_BASE_DATA_CPP_)) } // namespace cgogn -#endif // CORE_CMAP_MAP_BASE_DATA_H_ +#endif // CGOGN_CORE_CMAP_MAP_BASE_DATA_H_ diff --git a/cgogn/core/cmap/map_traits.h b/cgogn/core/cmap/map_traits.h index cc923e44..bf4c8a0b 100644 --- a/cgogn/core/cmap/map_traits.h +++ b/cgogn/core/cmap/map_traits.h @@ -21,11 +21,11 @@ * * *******************************************************************************/ -#ifndef CORE_MAP_MAP_TRAITS_H_ -#define CORE_MAP_MAP_TRAITS_H_ +#ifndef CGOGN_CORE_MAP_MAP_TRAITS_H_ +#define CGOGN_CORE_MAP_MAP_TRAITS_H_ #include -#include +#include namespace cgogn { @@ -37,4 +37,4 @@ struct DefaultMapTraits } // namespace cgogn -#endif // CORE_MAP_MAP_TRAITS_H_ +#endif // CGOGN_CORE_MAP_MAP_TRAITS_H_ diff --git a/cgogn/core/container/chunk_array.cpp b/cgogn/core/container/chunk_array.cpp index 13926ef2..3dcc5f96 100644 --- a/cgogn/core/container/chunk_array.cpp +++ b/cgogn/core/container/chunk_array.cpp @@ -22,10 +22,10 @@ *******************************************************************************/ #define CGOGN_CORE_DLL_EXPORT -#define CORE_CONTAINER_CHUNK_ARRAY_CPP_ +#define CGOGN_CORE_CONTAINER_CHUNK_ARRAY_CPP_ -#include -#include +#include +#include namespace cgogn { diff --git a/cgogn/core/container/chunk_array.h b/cgogn/core/container/chunk_array.h index 02b9ef6e..4e0627b2 100644 --- a/cgogn/core/container/chunk_array.h +++ b/cgogn/core/container/chunk_array.h @@ -21,8 +21,8 @@ * * *******************************************************************************/ -#ifndef CORE_CONTAINER_CHUNK_ARRAY_H_ -#define CORE_CONTAINER_CHUNK_ARRAY_H_ +#ifndef CGOGN_CORE_CONTAINER_CHUNK_ARRAY_H_ +#define CGOGN_CORE_CONTAINER_CHUNK_ARRAY_H_ #include #include @@ -30,11 +30,12 @@ #include #include -#include -#include -#include -#include - +#include +#include +#include +#include +#include +#include namespace cgogn { @@ -55,7 +56,7 @@ class ChunkArray : public ChunkArrayGen protected: - /// vector of block pointers + // vector of block pointers std::vector table_data_; public: @@ -63,6 +64,12 @@ class ChunkArray : public ChunkArrayGen /** * @brief Constructor of ChunkArray */ + inline ChunkArray(const std::string& name) : + Inherit(name, name_of_type(T())) + { + table_data_.reserve(1024u); + } + inline ChunkArray() : Inherit() { table_data_.reserve(1024u); @@ -80,21 +87,31 @@ class ChunkArray : public ChunkArrayGen * @brief create a ChunkArray * @return generic pointer */ - ChunkArrayGen* clone() const override + std::unique_ptr clone(const std::string& clone_name) const override { - return new Self(); + if (clone_name == this->name_) + return nullptr; + return std::unique_ptr(new Self(clone_name)); } - void swap(Self& ca) + bool swap(Inherit* cag) override { - table_data_.swap(ca.table_data_); - } + Self* ca = dynamic_cast(cag); + if (!ca) + { + cgogn_log_warning("swap") << "Warning: trying to swap attribute of different type"; + return false; + } - bool is_boolean_array() const override - { - return false; + table_data_.swap(ca->table_data_); + return true; } +// bool is_boolean_array() const override +// { +// return false; +// } + /** * @brief add a chunk (T[CHUNKSIZE]) */ @@ -188,6 +205,28 @@ class ChunkArray : public ChunkArrayGen table_data_[dst / CHUNKSIZE][dst % CHUNKSIZE] = table_data_[src / CHUNKSIZE][src % CHUNKSIZE]; } + /** + * @brief copy an element (of another C.A.) to another one + * @param dst destination index + * @param cag_src chunk_array source (Precond: same type as this) + * @param src source index + */ + void copy_external_element(uint32 dst, Inherit* cag_src, uint32 src) override + { + Self* ca = static_cast(cag_src); + table_data_[dst / CHUNKSIZE][dst % CHUNKSIZE] = ca->table_data_[src / CHUNKSIZE][src % CHUNKSIZE]; + } + + /** + * @brief move an element to another one + * @param dst destination index + * @param src source index + */ + void move_element(uint32 dst, uint32 src) override + { + table_data_[dst / CHUNKSIZE][dst % CHUNKSIZE] = std::move(table_data_[src / CHUNKSIZE][src % CHUNKSIZE]); + } + /** * @brief swap two elements * @param idx1 first element index @@ -379,46 +418,68 @@ class ChunkArray : public ChunkArrayGen table_data_[i / CHUNKSIZE][i % CHUNKSIZE] = v; } - inline void set_all_values( const T& v) + inline void set_all_values(const T& v) { for(T* chunk : table_data_) { - for(uint32 i=0; i::type()); + } + + virtual uint32 get_nb_components() const override + { + // Warning : the line 0 might be unused. + return type_traits::get_nb_components(this->operator [](0u)); + } + + virtual void export_element(uint32 idx, std::ostream& o, bool binary) const override + { + serialization::ostream_writer(o, binary, this->operator [](idx)); + } }; /** - * @brief specialized version of ChunkArray for bool data. One bit per bool + * @brief separate version of ChunkArray specialized for bool data. One bit per bool. */ template -class ChunkArray : public ChunkArrayGen +class ChunkArrayBool : public ChunkArrayGen { public: using Inherit = ChunkArrayGen; - using Self = ChunkArray; + using Self = ChunkArrayBool; using value_type = uint32; protected: - /// vector of block pointers + // ensure we can use CHUNK_SIZE value < 32 + const int BOOLS_PER_INT = (CHUNKSIZE<32u) ? CHUNKSIZE : 32u; + + // vector of block pointers std::vector table_data_; public: - inline ChunkArray() : ChunkArrayGen() + inline ChunkArrayBool(const std::string& name) : + Inherit(name, name_of_type(bool())) { table_data_.reserve(1024u); } - ChunkArray(const Self& ca) = delete; - ChunkArray(Self&& ca) = delete; - ChunkArray& operator=(Self&& ca) = delete; - ChunkArray& operator=(Self& ca) = delete; + inline ChunkArrayBool() : Inherit() + { + table_data_.reserve(1024u); + } - ~ChunkArray() override + CGOGN_NOT_COPYABLE_NOR_MOVABLE(ChunkArrayBool); + + ~ChunkArrayBool() override { for(auto chunk : table_data_) delete[] chunk; @@ -428,23 +489,38 @@ class ChunkArray : public ChunkArrayGen * @brief create a ChunkArray * @return generic pointer */ - ChunkArrayGen* clone() const override + std::unique_ptr clone(const std::string& clone_name) const override { - return new Self(); + if (clone_name == this->name_) + return nullptr; + return std::unique_ptr(new Self(clone_name)); } - bool is_boolean_array() const override + bool swap(Inherit* cag) override { + Self* ca = dynamic_cast(cag); + if (!ca) + { + cgogn_log_warning("swap") << "Warning: trying to swap attribute of different type"; + return false; + } + + table_data_.swap(ca->table_data_); return true; } +// bool is_boolean_array() const override +// { +// return true; +// } + /** * @brief add a chunk (T[CHUNKSIZE/32]) */ void add_chunk() override { // adding the empty parentheses for default-initialization - table_data_.push_back(new uint32[CHUNKSIZE/32u]()); + table_data_.push_back(new uint32[CHUNKSIZE/BOOLS_PER_INT]()); } /** @@ -481,7 +557,7 @@ class ChunkArray : public ChunkArrayGen */ uint32 capacity() const override { - return uint32(table_data_.size())*CHUNKSIZE/32u; + return uint32(table_data_.size())*CHUNKSIZE/BOOLS_PER_INT; } /** @@ -532,6 +608,18 @@ class ChunkArray : public ChunkArrayGen set_value(dst, this->operator[](src)); } + /** + * @brief copy an element (of another C.A.) to another one + * @param dst destination index + * @param cag_src chunk_array source (Precond: same type as this) + * @param src source index + */ + void copy_external_element(uint32 dst, Inherit* cag_src, uint32 src) override + { + Self* ca = static_cast(cag_src); + set_value(dst, ca->operator[](src)); + } + /** * @brief swap two elements * @param idx1 first element index @@ -555,10 +643,9 @@ class ChunkArray : public ChunkArrayGen return; } - // round nbLines to 32 multiple - if (nb_lines % 32u) - nb_lines = ((nb_lines / 32u) + 1u) * 32u; + if (nb_lines % BOOLS_PER_INT) + nb_lines = ((nb_lines / BOOLS_PER_INT) + 1u) * BOOLS_PER_INT; cgogn_assert(nb_lines / CHUNKSIZE <= table_data_.size()); // TODO: if (nb_lines==0) nb_lines = CHUNKSIZE*table_data_.size(); ?? @@ -570,13 +657,10 @@ class ChunkArray : public ChunkArrayGen // save number of lines serialization::save(fs, &nb_lines, 1); - const uint32 nbc = get_nb_chunks() - 1u; // save data chunks except last for(uint32 i = 0u; i < nbc; ++i) - { fs.write(reinterpret_cast(table_data_[i]), CHUNKSIZE / 8u); // /8 because bool = 1 bit & octet = 8 bit - } // save last const uint32 nb = nb_lines - nbc*CHUNKSIZE; @@ -626,8 +710,8 @@ class ChunkArray : public ChunkArrayGen const uint32 jj = i / CHUNKSIZE; cgogn_assert(jj < table_data_.size()); const uint32 j = i % CHUNKSIZE; - const uint32 x = j/32u; - const uint32 y = j%32u; + const uint32 x = j / BOOLS_PER_INT; + const uint32 y = j % BOOLS_PER_INT; const uint32 mask = 1u << y; @@ -639,8 +723,8 @@ class ChunkArray : public ChunkArrayGen const uint32 jj = i / CHUNKSIZE; cgogn_assert(jj < table_data_.size()); const uint32 j = i % CHUNKSIZE; - const uint32 x = j / 32u; - const uint32 y = j % 32u; + const uint32 x = j / BOOLS_PER_INT; + const uint32 y = j % BOOLS_PER_INT; const uint32 mask = 1u << y; table_data_[jj][x] &= ~mask; } @@ -650,8 +734,8 @@ class ChunkArray : public ChunkArrayGen const uint32 jj = i / CHUNKSIZE; cgogn_assert(jj < table_data_.size()); const uint32 j = i % CHUNKSIZE; - const uint32 x = j / 32u; - const uint32 y = j % 32u; + const uint32 x = j / BOOLS_PER_INT; + const uint32 y = j % BOOLS_PER_INT; const uint32 mask = 1u << y; table_data_[jj][x] |= mask; } @@ -661,8 +745,8 @@ class ChunkArray : public ChunkArrayGen const uint32 jj = i / CHUNKSIZE; cgogn_assert(jj < table_data_.size()); const uint32 j = i % CHUNKSIZE; - const uint32 x = j / 32u; - const uint32 y = j % 32u; + const uint32 x = j / BOOLS_PER_INT; + const uint32 y = j % BOOLS_PER_INT; const uint32 mask = 1u << y; if (b) table_data_[jj][x] |= mask; @@ -681,7 +765,7 @@ class ChunkArray : public ChunkArrayGen { const uint32 jj = i / CHUNKSIZE; cgogn_assert(jj < table_data_.size()); - const uint32 j = (i % CHUNKSIZE)/32u; + const uint32 j = (i % CHUNKSIZE) / BOOLS_PER_INT; table_data_[jj][j] = 0u; } @@ -690,7 +774,7 @@ class ChunkArray : public ChunkArrayGen for (uint32 * const ptr : table_data_) { //#pragma omp for - for (int32 j = 0; j < int32(CHUNKSIZE/32); ++j) + for (int32 j = 0; j < int32(CHUNKSIZE / BOOLS_PER_INT); ++j) ptr[j] = 0u; } } @@ -699,20 +783,35 @@ class ChunkArray : public ChunkArrayGen // { // for (auto ptr : table_data_) // { -// for (uint32 j = 0u; j < CHUNKSIZE/32u; ++j) +// for (uint32 j = 0u; j < CHUNKSIZE/BOOLS_PER_INT; ++j) // *ptr++ = 0xffffffff; // } // } + + virtual std::string get_nested_type_name() const override + { + return name_of_type(bool()); + } + + virtual uint32 get_nb_components() const override + { + return 1u; + } + + virtual void export_element(uint32 idx, std::ostream& o, bool binary) const override + { + serialization::ostream_writer(o,binary, this->operator [](idx)); + } }; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_CONTAINER_CHUNK_ARRAY_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_CORE_CONTAINER_CHUNK_ARRAY_CPP_)) extern template class CGOGN_CORE_API ChunkArray; extern template class CGOGN_CORE_API ChunkArray; extern template class CGOGN_CORE_API ChunkArray; extern template class CGOGN_CORE_API ChunkArray>; extern template class CGOGN_CORE_API ChunkArray>; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_CONTAINER_CHUNK_ARRAY_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_CORE_CONTAINER_CHUNK_ARRAY_CPP_)) } // namespace cgogn -#endif // CORE_CONTAINER_CHUNK_ARRAY_H_ +#endif // CGOGN_CORE_CONTAINER_CHUNK_ARRAY_H_ diff --git a/cgogn/core/container/chunk_array_container.cpp b/cgogn/core/container/chunk_array_container.cpp index baa067f6..5c7ddbdd 100644 --- a/cgogn/core/container/chunk_array_container.cpp +++ b/cgogn/core/container/chunk_array_container.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_CORE_DLL_EXPORT -#define CORE_CONTAINER_CHUNK_ARRAY_CONTAINER_CPP_ +#define CGOGN_CORE_CONTAINER_CHUNK_ARRAY_CONTAINER_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/core/container/chunk_array_container.h b/cgogn/core/container/chunk_array_container.h index a222a741..24139231 100644 --- a/cgogn/core/container/chunk_array_container.h +++ b/cgogn/core/container/chunk_array_container.h @@ -21,8 +21,8 @@ * * *******************************************************************************/ -#ifndef CORE_CONTAINER_CHUNK_ARRAY_CONTAINER_H_ -#define CORE_CONTAINER_CHUNK_ARRAY_CONTAINER_H_ +#ifndef CGOGN_CORE_CONTAINER_CHUNK_ARRAY_CONTAINER_H_ +#define CGOGN_CORE_CONTAINER_CHUNK_ARRAY_CONTAINER_H_ #include #include @@ -32,15 +32,15 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace cgogn { @@ -60,8 +60,10 @@ class ChunkArrayContainer using ChunkArrayGen = cgogn::ChunkArrayGen; template using ChunkArray = cgogn::ChunkArray; + using ChunkArrayBool = cgogn::ChunkArrayBool; template using ChunkStack = cgogn::ChunkStack; + using ChunkArrayFactory = cgogn::ChunkArrayFactory; /** * constante d'attribut inconnu @@ -82,7 +84,7 @@ class ChunkArrayContainer /** * vector of pointers to Marker ChunkArray */ - std::vector*> table_marker_arrays_; + std::vector table_marker_arrays_; /** * @brief ChunkArray of refs @@ -183,6 +185,9 @@ class ChunkArrayContainer delete ptr; } + const std::vector& get_names() const { return names_; } + const std::vector& get_type_names() const { return type_names_; } + /** * @brief get an attribute * @param attribute_name name of attribute @@ -192,7 +197,7 @@ class ChunkArrayContainer template ChunkArray* get_attribute(const std::string& attribute_name) const { - // first check if attribute already exist + // first check if attribute already exists uint32 index = get_array_index(attribute_name); if (index == UNKNOWN) { @@ -200,7 +205,29 @@ class ChunkArrayContainer return nullptr; } - return static_cast*>(table_arrays_[index]); + return dynamic_cast*>(table_arrays_[index]); + } + + ChunkArrayGen* get_attribute(const std::string& attribute_name) const + { + // first check if attribute already exists + uint32 index = get_array_index(attribute_name); + if (index == UNKNOWN) + { + cgogn_log_warning("get_attribute") << "Attribute \"" << attribute_name << "\" not found."; + return nullptr; + } + + return table_arrays_[index]; + } + + /** + * @brief get all attributes (generic pointers) + * @return + */ + inline std::vector& get_attributes() + { + return table_arrays_; } /** @@ -223,9 +250,9 @@ class ChunkArrayContainer } // create the new attribute - const std::string& typeName = name_of_type(T()); - ChunkArray* carr = new ChunkArray(); - ChunkArrayFactory::template register_CA(); + const std::string& type_name = name_of_type(T()); + ChunkArray* carr = new ChunkArray(attribute_name); + ChunkArrayFactory::template register_CA(); // reserve memory carr->set_nb_chunks(refs_.get_nb_chunks()); @@ -233,7 +260,7 @@ class ChunkArrayContainer // store pointer, name & typename. table_arrays_.push_back(carr); names_.push_back(attribute_name); - type_names_.push_back(typeName); + type_names_.push_back(type_name); return carr; } @@ -278,13 +305,68 @@ class ChunkArrayContainer return true; } + /** + * @brief swap the data of two chunk arrays of the container + * @param ptr1 pointer to first chunk array + * @param ptr2 pointer to second chunk array + * @return + */ + bool swap_data_attributes(const ChunkArrayGen* ptr1, const ChunkArrayGen* ptr2) + { + uint32 index1 = get_array_index(ptr1); + uint32 index2 = get_array_index(ptr2); + + if ((index1 == UNKNOWN) || (index2 == UNKNOWN)) + { + cgogn_log_warning("swap_data_attributes") << "Attribute not found."; + return false; + } + + if (index1 == index2) + { + cgogn_log_warning("swap_data_attributes") << "Same attributes."; + return false; + } + + table_arrays_[index1]->swap(table_arrays_[index2]); + + return true; + } + + template + bool copy_data_attribute(const ChunkArray* dest, const ChunkArray* src) + { + uint32 dest_index = get_array_index(dest); + uint32 src_index = get_array_index(src); + + if ((dest_index == UNKNOWN) || (src_index == UNKNOWN)) + { + cgogn_log_warning("copy_data_attributes") << "Attribute not found."; + return false; + } + + if (dest_index == src_index) + { + cgogn_log_warning("copy_data_attributes") << "Same attributes."; + return false; + } + + ChunkArray* dest_ca = static_cast*>(table_arrays_[dest_index]); + ChunkArray* src_ca = static_cast*>(table_arrays_[src_index]); + + for (uint32 it = begin(), last = end(); it < last; ++it) + (*dest_ca)[it] = (*src_ca)[it]; + + return true; + } + /** * @brief add a Marker attribute * @return pointer on created ChunkArray */ - ChunkArray* add_marker_attribute() + ChunkArrayBool* add_marker_attribute() { - ChunkArray* mca = new ChunkArray(); + ChunkArrayBool* mca = new ChunkArrayBool(); mca->set_nb_chunks(refs_.get_nb_chunks()); table_marker_arrays_.push_back(mca); return mca; @@ -295,7 +377,7 @@ class ChunkArrayContainer * @param ptr ChunkArray pointer to the attribute to remove * @return true if attribute exists and has been removed */ - void remove_marker_attribute(const ChunkArray* ptr) + void remove_marker_attribute(const ChunkArrayBool* ptr) { uint32 index = 0u; while (index < table_marker_arrays_.size() && table_marker_arrays_[index] != ptr) @@ -319,39 +401,6 @@ class ChunkArrayContainer return table_arrays_.size(); } - /** - * @brief get a chunk_array - * @param attribute_name name of the array - * @return pointer on typed chunk_array - */ - template - ChunkArray* get_data_array(const std::string& attribute_name) - { - uint32 index = get_array_index(attribute_name); - if (index == UNKNOWN) - return nullptr; - - ChunkArray* atm = dynamic_cast*>(table_arrays_[index]); - - cgogn_message_assert(atm != nullptr, "get_data_array : wrong type."); - - return atm; - } - - /** - * @brief get a chunk_array - * @param attribute_name name of the array - * @return pointer on virtual chunk_array - */ - ChunkArrayGen* get_virtual_data_array(const std::string& attribute_name) - { - uint32 index = get_array_index(attribute_name); - if (index == UNKNOWN) - return nullptr; - - return table_arrays_[index]; - } - /** * @brief size (number of used lines) * @return the number of lines @@ -432,7 +481,7 @@ class ChunkArrayContainer * @brief reverse end of container * @return the index before the last used line of the container in reverse order */ - uint32 real_rend() const + uint32 rend() const { return 0xffffffff; } @@ -499,8 +548,8 @@ class ChunkArrayContainer names_.swap(container.names_); type_names_.swap(container.type_names_); table_marker_arrays_.swap(container.table_marker_arrays_); - refs_.swap(container.refs_); - holes_stack_.swap(container.holes_stack_); + refs_.swap(&(container.refs_)); + holes_stack_.swap(&(container.holes_stack_)); std::swap(nb_used_lines_, container.nb_used_lines_); std::swap(nb_max_lines_, container.nb_max_lines_); } @@ -516,38 +565,38 @@ class ChunkArrayContainer /** * @brief container compacting - * @param map_old_new vector that contains a map from old indices to new indices (holes -> 0xffffffff) + * @return map_old_new vector that contains a map from old indices to new indices (holes & unchanged -> 0xffffffff) */ template - void compact(std::vector& map_old_new) + std::vector compact() { - map_old_new.clear(); - map_old_new.resize(end(), 0xffffffff); + if (this->holes_stack_.empty()) + return std::vector(); uint32 up = rbegin(); - uint32 down = 0u; - - while (down < up) + uint32 down = std::numeric_limits::max(); + std::vector map_old_new(up+1, std::numeric_limits::max()); + do { - if (!used(down)) - { + down = holes_stack_.head(); + if (down < nb_used_lines_) for(uint32 i = 0u; i < PRIMSIZE; ++i) { - unsigned rdown = down + PRIMSIZE-1u - i; + const uint32 rdown = down + PRIMSIZE-1u - i; map_old_new[up] = rdown; - copy_line(rdown, up,true,true); + move_line(rdown, up,true,true); rnext(up); } - down += PRIMSIZE; - } - else - down++; - } + holes_stack_.pop(); + }while (!holes_stack_.empty()); + // free unused memory blocks + const uint32 old_nb_blocks = this->nb_max_lines_/CHUNKSIZE + 1u; nb_max_lines_ = nb_used_lines_; + const uint32 new_nb_blocks = nb_max_lines_/CHUNKSIZE + 1u; - // free unused memory blocks - uint32 new_nb_blocks = nb_max_lines_/CHUNKSIZE + 1u; + if (old_nb_blocks == new_nb_blocks) + return map_old_new; for (auto arr : table_arrays_) arr->set_nb_chunks(new_nb_blocks); @@ -557,8 +606,80 @@ class ChunkArrayContainer refs_.set_nb_chunks(new_nb_blocks); - // clear holes - holes_stack_.clear(); + return map_old_new; + } + + + bool check_before_merge(const Self& cac) + { + for (uint32 i=0; i + std::vector merge(const Self& cac) + { + // mapping table of ca indices of cac in this + std::vector map_attrib(cac.names_.size()); + + // First check & find missing attributes + for (uint32 i=0; iset_nb_chunks(refs_.get_nb_chunks()); + table_arrays_.push_back(cag.release()); + names_.push_back(name); + type_names_.push_back(type_name); + } + else + if (cac.type_names_[i] == type_names_[j]) + map_attrib[i] = uint32(j); + } + + // check if nothing to do + if (cac.size()==0) + return std::vector(); + + // line mapping + std::vector map_old_new(cac.rbegin()+1u, std::numeric_limits::max()); + + // copy data + for (uint32 it=cac.begin(); it!= cac.end(); cac.next(it)) + { + uint32 new_lines = this->insert_lines(); + for(uint32 j = 0u; j < PRIMSIZE; ++j) + { + uint32 ol = it+j; + uint32 nl = new_lines+j; + map_old_new[ol] = nl; + uint32 nb_att = uint32(cac.table_arrays_.size()); + for (uint32 k=0; kcopy_external_element(nl, cac.table_arrays_[k], ol); + } + it += PRIMSIZE-1u; + } + + return map_old_new; } /************************************** @@ -691,6 +812,29 @@ class ChunkArrayContainer refs_[dst] = refs_[src]; } + /** + * @brief move the content of line src in line dst (with refs & markers) + * After the operation the behaviour is undefined when accessing to the content of the line src. + * @param dstIndex destination + * @param srcIndex source + * @param copy_markers, to specify if the marker should be copied. + * @param copy_refs, to specify if the refs should be copied. + */ + inline void move_line(uint32 dst, uint32 src, bool copy_markers, bool copy_refs) + { + for (auto ptr : table_arrays_) + ptr->move_element(dst, src); + + //for markers (i.e. uints) there is no gain moving, we can copy + if (copy_markers) + { + for (auto ptr : table_marker_arrays_) + ptr->copy_element(dst, src); + } + if (copy_refs) + refs_[dst] = refs_[src]; + } + /** * @brief increment the reference counter of the given line (only for PRIMSIZE==1) * @param index index of the line @@ -779,7 +923,7 @@ class ChunkArrayContainer cgogn_assert(fs.good()); // check and register all known types if necessaey - ChunkArrayFactory::register_known_types(); + ChunkArrayFactory::register_known_types(); // read info uint32 buff1[4]; @@ -805,21 +949,22 @@ class ChunkArrayContainer type_names_[i] = std::string(buff3); } cgogn_assert(fs.good()); + // read chunk array table_arrays_.reserve(buff1[0]); bool ok = true; for (uint32 i = 0u; i < names_.size();) { - ChunkArrayGen* cag = ChunkArrayFactory::create(type_names_[i]); + auto cag = ChunkArrayFactory::create(type_names_[i], names_[i]); if (cag) { - table_arrays_.push_back(cag); + table_arrays_.push_back(cag.release()); ok &= table_arrays_.back()->load(fs); ++i; } else { - cgogn_log_warning("ChunkArrayContainer::load") << "Could not load attribute \"" << names_[i] << "\" of type \""<< type_names_[i] << "\"."; + cgogn_log_warning("ChunkArrayContainer::load") << "Could not load attribute \"" << names_[i] << "\" of type \"" << type_names_[i] << "\"."; type_names_.erase(type_names_.begin()+i); names_.erase(names_.begin()+i); ChunkArrayGen::skip(fs); @@ -831,13 +976,11 @@ class ChunkArrayContainer } }; - - -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_CONTAINER_CHUNK_ARRAY_CONTAINER_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_CORE_CONTAINER_CHUNK_ARRAY_CONTAINER_CPP_)) extern template class CGOGN_CORE_API ChunkArrayContainer; extern template class CGOGN_CORE_API ChunkArrayContainer; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_CONTAINER_CHUNK_ARRAY_CONTAINER_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_CORE_CONTAINER_CHUNK_ARRAY_CONTAINER_CPP_)) } // namespace cgogn -#endif // CORE_CONTAINER_CHUNK_ARRAY_CONTAINER_H_ +#endif // CGOGN_CORE_CONTAINER_CHUNK_ARRAY_CONTAINER_H_ diff --git a/cgogn/core/container/chunk_array_factory.cpp b/cgogn/core/container/chunk_array_factory.cpp index 83efa48e..9c730236 100644 --- a/cgogn/core/container/chunk_array_factory.cpp +++ b/cgogn/core/container/chunk_array_factory.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_CORE_DLL_EXPORT -#define CORE_CONTAINER_CHUNK_ARRAY_FACTORY_CPP_ +#define CGOGN_CORE_CONTAINER_CHUNK_ARRAY_FACTORY_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/core/container/chunk_array_factory.h b/cgogn/core/container/chunk_array_factory.h index 37b2ba70..1a9200d7 100644 --- a/cgogn/core/container/chunk_array_factory.h +++ b/cgogn/core/container/chunk_array_factory.h @@ -21,13 +21,13 @@ * * *******************************************************************************/ -#ifndef CORE_CONTAINER_CHUNK_ARRAY_FACTORY_H_ -#define CORE_CONTAINER_CHUNK_ARRAY_FACTORY_H_ +#ifndef CGOGN_CORE_CONTAINER_CHUNK_ARRAY_FACTORY_H_ +#define CGOGN_CORE_CONTAINER_CHUNK_ARRAY_FACTORY_H_ -#include -#include -#include -#include +#include +#include +#include +#include #include #include @@ -40,16 +40,18 @@ namespace cgogn template class ChunkArrayFactory { - static_assert(CHUNKSIZE >= 1u,"ChunkSize must be at least 1"); - static_assert(!(CHUNKSIZE & (CHUNKSIZE - 1)),"CHUNKSIZE must be a power of 2"); + static_assert(CHUNKSIZE >= 1u, "ChunkSize must be at least 1"); + static_assert(!(CHUNKSIZE & (CHUNKSIZE - 1)), "CHUNKSIZE must be a power of 2"); public: + using Self = ChunkArrayFactory; using ChunkArrayGenPtr = std::unique_ptr< ChunkArrayGen >; using NamePtrMap = std::map; using UniqueNamePtrMap = std::unique_ptr; CGOGN_NOT_COPYABLE_NOR_MOVABLE(ChunkArrayFactory); + static UniqueNamePtrMap map_CA_; /** @@ -89,8 +91,8 @@ class ChunkArrayFactory register_CA(); register_CA(); register_CA(); - register_CA>(); - register_CA>(); + register_CA>(); + register_CA>(); // NOT TODO : add Eigen. known_types_initialized_ = true; @@ -101,17 +103,15 @@ class ChunkArrayFactory * @param keyType typename of type store in ChunkArray * @return ptr on created ChunkArray */ - static ChunkArrayGen* create(const std::string& keyType) + static ChunkArrayGenPtr create(const std::string& type_name, const std::string& name) { - ChunkArrayGen* tmp = nullptr; - typename NamePtrMap::const_iterator it = map_CA_->find(keyType); + ChunkArrayGenPtr tmp = nullptr; + typename NamePtrMap::const_iterator it = map_CA_->find(type_name); if(it != map_CA_->end()) - { - tmp = (it->second)->clone(); - } + tmp = (it->second)->clone(name); else - cgogn_log_warning("ChunkArrayFactory::create") << "Type \"" << keyType << "\" is not registred in ChunkArrayFactory."; + cgogn_log_warning("ChunkArrayFactory::create") << "Type \"" << type_name << "\" is not registered in ChunkArrayFactory."; return tmp; } @@ -120,18 +120,19 @@ class ChunkArrayFactory { ChunkArrayFactory::map_CA_ = make_unique(); } - private: + +private: + inline ChunkArrayFactory() {} }; template typename ChunkArrayFactory::UniqueNamePtrMap ChunkArrayFactory::map_CA_ = nullptr; - -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_CONTAINER_CHUNK_ARRAY_FACTORY_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_CORE_CONTAINER_CHUNK_ARRAY_FACTORY_CPP_)) extern template class CGOGN_CORE_API ChunkArrayFactory; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_CONTAINER_CHUNK_ARRAY_FACTORY_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_CORE_CONTAINER_CHUNK_ARRAY_FACTORY_CPP_)) } // namespace cgogn -#endif // CORE_CONTAINER_CHUNK_ARRAY_FACTORY_H_ +#endif // CGOGN_CORE_CONTAINER_CHUNK_ARRAY_FACTORY_H_ diff --git a/cgogn/core/container/chunk_array_gen.cpp b/cgogn/core/container/chunk_array_gen.cpp index eca2c7d5..870521a5 100644 --- a/cgogn/core/container/chunk_array_gen.cpp +++ b/cgogn/core/container/chunk_array_gen.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_CORE_DLL_EXPORT -#define CORE_CONTAINER_CHUNK_ARRAY_GEN_CPP_ +#define CGOGN_CORE_CONTAINER_CHUNK_ARRAY_GEN_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/core/container/chunk_array_gen.h b/cgogn/core/container/chunk_array_gen.h index e68fb453..cd7836a1 100644 --- a/cgogn/core/container/chunk_array_gen.h +++ b/cgogn/core/container/chunk_array_gen.h @@ -21,15 +21,16 @@ * * *******************************************************************************/ -#ifndef CORE_CONTAINER_CHUNK_ARRAY_GEN_H_ -#define CORE_CONTAINER_CHUNK_ARRAY_GEN_H_ +#ifndef CGOGN_CORE_CONTAINER_CHUNK_ARRAY_GEN_H_ +#define CGOGN_CORE_CONTAINER_CHUNK_ARRAY_GEN_H_ -#include -#include +#include +#include #include #include #include +#include namespace cgogn { @@ -46,13 +47,24 @@ class ChunkArrayGen using Self = ChunkArrayGen; - inline ChunkArrayGen() {} + inline ChunkArrayGen(const std::string& name, const std::string& type_name) : + name_(name), + type_name_(type_name) + {} + + inline ChunkArrayGen() + {} + CGOGN_NOT_COPYABLE_NOR_MOVABLE(ChunkArrayGen); protected: std::vector external_refs_; + std::string name_; + + std::string type_name_; + public: /** @@ -66,6 +78,14 @@ class ChunkArrayGen } } + inline const std::string& get_name() const { return name_; } + + inline const std::string& get_type_name() const { return type_name_; } + + virtual std::string get_nested_type_name() const = 0; + + virtual uint32 get_nb_components() const = 0; + void add_external_ref(ChunkArrayGen** ref) { cgogn_message_assert(*ref == this, "ChunkArrayGen add_external_ref on other ChunkArrayGen"); @@ -82,12 +102,14 @@ class ChunkArrayGen } /** - * @brief create a ChunkArray object without knowning type + * @brief create a ChunkArray object without knowing type * @return generic pointer */ - virtual Self* clone() const = 0; + virtual std::unique_ptr clone(const std::string& clone_name) const = 0; + + virtual bool swap(Self*) = 0; - virtual bool is_boolean_array() const = 0; +// virtual bool is_boolean_array() const = 0; /** * @brief add a chunk (T[CHUNKSIZE]) @@ -138,6 +160,24 @@ class ChunkArrayGen */ virtual void copy_element(uint32 dst, uint32 src) = 0; + /** + * @brief copy an element (of another C.A.) to another one + * @param dst destination index + * @param cag_src chunk_array source ptr (Precond: same type as this) + * @param src source index + */ + virtual void copy_external_element(uint32 dst, Self* cag_src, uint32 src) = 0; + + /** + * @brief move an element to another one + * @param dst destination index + * @param src source index + */ + virtual void move_element(uint32 dst, uint32 src) + { + this->copy_element(dst,src); + } + /** * @brief swap two elements * @param idx1 first element index @@ -152,6 +192,8 @@ class ChunkArrayGen */ virtual void save(std::ostream& fs, uint32 nb_lines) const = 0; + virtual void export_element(uint32 idx, std::ostream& o, bool binary) const = 0; + /** * @brief load * @param fs file stream @@ -173,10 +215,10 @@ class ChunkArrayGen } }; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_CONTAINER_CHUNK_ARRAY_GEN_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_CORE_CONTAINER_CHUNK_ARRAY_GEN_CPP_)) extern template class CGOGN_CORE_API ChunkArrayGen; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_CONTAINER_CHUNK_ARRAY_GEN_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_CORE_CONTAINER_CHUNK_ARRAY_GEN_CPP_)) } // namespace cgogn -#endif // CORE_CONTAINER_CHUNK_ARRAY_GEN_H_ +#endif // CGOGN_CORE_CONTAINER_CHUNK_ARRAY_GEN_H_ diff --git a/cgogn/core/container/chunk_stack.cpp b/cgogn/core/container/chunk_stack.cpp index 0883eceb..f7063a5f 100644 --- a/cgogn/core/container/chunk_stack.cpp +++ b/cgogn/core/container/chunk_stack.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_CORE_DLL_EXPORT -#define CORE_CONTAINER_CHUNK_STACK_CPP_ +#define CGOGN_CORE_CONTAINER_CHUNK_STACK_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/core/container/chunk_stack.h b/cgogn/core/container/chunk_stack.h index c6720eb7..a4525f17 100644 --- a/cgogn/core/container/chunk_stack.h +++ b/cgogn/core/container/chunk_stack.h @@ -21,12 +21,12 @@ * * *******************************************************************************/ -#ifndef CORE_CONTAINER_CHUNK_STACK_H_ -#define CORE_CONTAINER_CHUNK_STACK_H_ +#ifndef CGOGN_CORE_CONTAINER_CHUNK_STACK_H_ +#define CGOGN_CORE_CONTAINER_CHUNK_STACK_H_ -#include -#include -#include +#include +#include +#include namespace cgogn { @@ -141,17 +141,22 @@ class ChunkStack : public ChunkArray Inherit::clear(); } - void swap(Self &cs) + bool swap(ChunkArrayGen* cag) override { - Inherit::swap(cs); - std::swap(stack_size_, cs.stack_size_); + if (Inherit::swap(cag)) + { + Self* cs = dynamic_cast(cag); + std::swap(stack_size_, cs->stack_size_); + return true; + } + return false; } }; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_CONTAINER_CHUNK_STACK_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_CORE_CONTAINER_CHUNK_STACK_CPP_)) extern template class CGOGN_CORE_API ChunkStack; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_CONTAINER_CHUNK_STACK_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_CORE_CONTAINER_CHUNK_STACK_CPP_)) } // namespace cgogn -#endif // CORE_CONTAINER_CHUNK_STACK_H_ +#endif // CGOGN_CORE_CONTAINER_CHUNK_STACK_H_ diff --git a/cgogn/core/dll.h b/cgogn/core/dll.h index 9dc8f4fc..861a4d81 100644 --- a/cgogn/core/dll.h +++ b/cgogn/core/dll.h @@ -21,8 +21,8 @@ * * *******************************************************************************/ -#ifndef CORE_DLL_H_ -#define CORE_DLL_H_ +#ifndef CGOGN_CORE_DLL_H_ +#define CGOGN_CORE_DLL_H_ /** * \brief Linkage declaration for CGOGN symbols. @@ -39,4 +39,4 @@ #define CGOGN_CORE_API #endif -#endif // CORE_DLL_H_ +#endif // CGOGN_CORE_DLL_H_ diff --git a/cgogn/core/examples/chunk_array/CMakeLists.txt b/cgogn/core/examples/chunk_array/CMakeLists.txt index ae2ed9bc..34cf3755 100644 --- a/cgogn/core/examples/chunk_array/CMakeLists.txt +++ b/cgogn/core/examples/chunk_array/CMakeLists.txt @@ -1,30 +1,16 @@ project(${CGOGN_TEST_PREFIX}chunk_array - LANGUAGES CXX - ) + LANGUAGES CXX +) -#get_property(cgogn_core_includes -# TARGET cgogn_core -# PROPERTY INCLUDE_DIRECTORIES -# ) +find_package(cgogn_core REQUIRED) add_executable(chunk_array chunk_array.cpp) -target_link_libraries(chunk_array cgogn_core) +target_link_libraries(chunk_array ${cgogn_core_LIBRARIES}) #target_include_directories(test_chunk_array PRIVATE ${cgogn_core_includes}) add_executable(bench_chunk_array bench_chunk_array.cpp) -target_link_libraries(bench_chunk_array cgogn_core) +target_link_libraries(bench_chunk_array ${cgogn_core_LIBRARIES}) #target_include_directories(bench_chunk_array PRIVATE ${cgogn_core_includes}) add_executable(chunk_array2 chunk_array2.cpp) -target_link_libraries(chunk_array2 cgogn_core) - - -install(TARGETS chunk_array - EXPORT ${PROJECT_NAME}Targets - RUNTIME DESTINATION "bin/test" - ) - -install(TARGETS bench_chunk_array - EXPORT ${PROJECT_NAME}Targets - RUNTIME DESTINATION "bin/bench" - ) +target_link_libraries(chunk_array2 ${cgogn_core_LIBRARIES}) diff --git a/cgogn/core/examples/chunk_array/bench_chunk_array.cpp b/cgogn/core/examples/chunk_array/bench_chunk_array.cpp index 274d6f72..4e0ca894 100644 --- a/cgogn/core/examples/chunk_array/bench_chunk_array.cpp +++ b/cgogn/core/examples/chunk_array/bench_chunk_array.cpp @@ -1,6 +1,6 @@ -#include -#include +#include +#include #define BLK_SZ 4096 using namespace cgogn; @@ -34,6 +34,21 @@ class Vec3f { return "Vec3f"; } + + inline uint32 size() const + { + return 3u; + } + + inline float32& operator[](std::size_t i) + { + return data_[i]; + } + + inline const float32& operator[](std::size_t i) const + { + return data_[i]; + } }; const uint32 NB_LINES = 20000000; @@ -114,8 +129,8 @@ int test3() { cgogn_log_info("bench_chunk_array") << "= TEST 3 = random bool cleaning" ; - ChunkArrayContainer container; - ChunkArray* att1 = container.add_attribute("bools"); + ChunkArrayContainer container; + ChunkArrayBool* att1 = container.add_marker_attribute(); for (uint32 i = 0; i < NB_LINES; ++i) container.insert_lines<1>(); @@ -142,8 +157,8 @@ int test4() { cgogn_log_info("bench_chunk_array") << "= TEST 4 = random bool cleaning with set_false_byte" ; - ChunkArrayContainer container; - ChunkArray* att1 = container.add_attribute("bools"); + ChunkArrayContainer container; + ChunkArrayBool* att1 = container.add_marker_attribute(); for (uint32 i = 0; i < NB_LINES; ++i) container.insert_lines<1>(); diff --git a/cgogn/core/examples/chunk_array/chunk_array.cpp b/cgogn/core/examples/chunk_array/chunk_array.cpp index 258852e9..3b7e56ca 100644 --- a/cgogn/core/examples/chunk_array/chunk_array.cpp +++ b/cgogn/core/examples/chunk_array/chunk_array.cpp @@ -1,5 +1,5 @@ -#include +#include #include @@ -70,8 +70,8 @@ int test1() container.remove_lines<1>(19); container.remove_lines<1>(35); - std::vector mapOldNew; - container.compact<1>(mapOldNew); + + container.compact<1>(); for(uint32 i = container.begin(); i != container.end(); container.next(i)) { @@ -121,8 +121,7 @@ int test2() std::cout << i << ": " << (*att1)[i] << std::endl; std::cout << "-Compact--------------------------------------" << std::endl; - std::vector mapOldNew; - container.compact<3>(mapOldNew); + container.compact<3>(); for(uint32 i = container.begin(); i != container.end(); container.next(i)) std::cout << i << ": " << (*att1)[i] << std::endl; diff --git a/cgogn/core/examples/chunk_array/chunk_array2.cpp b/cgogn/core/examples/chunk_array/chunk_array2.cpp index d8ace780..82db6004 100644 --- a/cgogn/core/examples/chunk_array/chunk_array2.cpp +++ b/cgogn/core/examples/chunk_array/chunk_array2.cpp @@ -1,5 +1,5 @@ -#include +#include #include #include diff --git a/cgogn/core/examples/map/CMakeLists.txt b/cgogn/core/examples/map/CMakeLists.txt index b2442d18..520cc0f2 100644 --- a/cgogn/core/examples/map/CMakeLists.txt +++ b/cgogn/core/examples/map/CMakeLists.txt @@ -2,12 +2,7 @@ project(${CGOGN_TEST_PREFIX}map LANGUAGES CXX ) -add_executable(map map.cpp) -target_link_libraries(map cgogn_core) - -#get_property(cgogn_core_includes -# TARGET cgogn_core -# PROPERTY INCLUDE_DIRECTORIES -# ) -#target_include_directories(test_map PRIVATE ${cgogn_core_includes}) +find_package(cgogn_core REQUIRED) +add_executable(map map.cpp) +target_link_libraries(map ${cgogn_core_LIBRARIES}) diff --git a/cgogn/core/examples/map/map.cpp b/cgogn/core/examples/map/map.cpp index f704f270..431cdfce 100644 --- a/cgogn/core/examples/map/map.cpp +++ b/cgogn/core/examples/map/map.cpp @@ -1,10 +1,10 @@ -#include -#include -#include +#include +#include +#include -#include -#include +#include +#include using namespace cgogn; using namespace cgogn::numerics; @@ -15,17 +15,17 @@ using Map3 = CMap3; template -void fonc_const(const typename MAP::template VertexAttributeHandler& ah); +void fonc_const(const typename MAP::template VertexAttribute& ah); template -void fonc_non_const(typename MAP::template VertexAttributeHandler& ah); +void fonc_non_const(typename MAP::template VertexAttribute& ah); template int test1(MAP& map); template -void fonc_const(const typename MAP::template VertexAttributeHandler& ah) +void fonc_const(const typename MAP::template VertexAttribute& ah) { for (const float32& f : ah) { @@ -33,12 +33,12 @@ void fonc_const(const typename MAP::template VertexAttributeHandler& ah } // equivalent to - for (typename MAP::template VertexAttributeHandler::const_iterator it = ah.begin(); it != ah.end(); ++it) + for (typename MAP::template VertexAttribute::const_iterator it = ah.begin(); it != ah.end(); ++it) cgogn_log_info("example_map") << *it; } template -void fonc_non_const(typename MAP::template VertexAttributeHandler& ah) +void fonc_non_const(typename MAP::template VertexAttribute& ah) { for (float32& f : ah) { @@ -47,7 +47,7 @@ void fonc_non_const(typename MAP::template VertexAttributeHandler& ah) } // equivalent to - for (typename MAP::template VertexAttributeHandler::iterator it = ah.begin(); it != ah.end(); ++it) + for (typename MAP::template VertexAttribute::iterator it = ah.begin(); it != ah.end(); ++it) { *it /= 2.0f; } @@ -60,12 +60,12 @@ int test1(MAP& map) using Face = typename MAP::Face; // add an attribute on vertex of map with - typename MAP::template VertexAttributeHandler ah = map.template add_attribute("floats"); + typename MAP::template VertexAttribute ah = map.template add_attribute("floats"); - typename MAP::template FaceAttributeHandler ahf = map.template add_attribute("floats"); + typename MAP::template FaceAttribute ahf = map.template add_attribute("floats"); // get attribute and change type (dangerous!) - typename MAP::template VertexAttributeHandler ahf2 = map.template get_attribute_force_type("floats"); + typename MAP::template VertexAttribute ahf2 = map.template get_attribute_force_type("floats"); map.remove_attribute(ahf); cgogn_log_info("example_map") << "ahf valid : " << std::boolalpha << ahf.is_valid(); diff --git a/cgogn/core/tests/CMakeLists.txt b/cgogn/core/tests/CMakeLists.txt index d78df315..f2d48a98 100644 --- a/cgogn/core/tests/CMakeLists.txt +++ b/cgogn/core/tests/CMakeLists.txt @@ -2,6 +2,8 @@ project(cgogn_core_test LANGUAGES CXX ) +find_package(cgogn_core REQUIRED) + set(SOURCE_FILES basic/dart_test.cpp basic/cell_test.cpp @@ -24,11 +26,10 @@ set(SOURCE_FILES add_executable(${PROJECT_NAME} ${SOURCE_FILES}) -target_link_libraries(cgogn_core_test gtest gmock cgogn_core) +target_link_libraries(cgogn_core_test gtest gmock ${cgogn_core_LIBRARIES}) target_include_directories(cgogn_core_test PRIVATE ${CMAKE_SOURCE_DIR}/thirdparty/googletest-master/googletest/include ${CMAKE_SOURCE_DIR}/thirdparty/googletest-master/googlemock/include) link_directories(${CMAKE_SOURCE_DIR}/thirdparty/googletest-master/googletest/lib) link_directories(${CMAKE_SOURCE_DIR}/thirdparty/googletest-master/googlemock/lib) - add_test(NAME "${PROJECT_NAME}" WORKING_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" COMMAND ${PROJECT_NAME}) diff --git a/cgogn/core/tests/basic/cell_test.cpp b/cgogn/core/tests/basic/cell_test.cpp index 64ac5c3e..980efc32 100644 --- a/cgogn/core/tests/basic/cell_test.cpp +++ b/cgogn/core/tests/basic/cell_test.cpp @@ -23,7 +23,7 @@ #include -#include +#include namespace cgogn { diff --git a/cgogn/core/tests/basic/dart_test.cpp b/cgogn/core/tests/basic/dart_test.cpp index 1d64697f..117e5f18 100644 --- a/cgogn/core/tests/basic/dart_test.cpp +++ b/cgogn/core/tests/basic/dart_test.cpp @@ -23,7 +23,7 @@ #include -#include +#include namespace cgogn { diff --git a/cgogn/core/tests/cmap/cmap0_test.cpp b/cgogn/core/tests/cmap/cmap0_test.cpp index d840a7d5..4ead6dc2 100644 --- a/cgogn/core/tests/cmap/cmap0_test.cpp +++ b/cgogn/core/tests/cmap/cmap0_test.cpp @@ -23,7 +23,7 @@ #include -#include +#include namespace cgogn { @@ -45,7 +45,7 @@ class CMap0Test : public ::testing::Test public: using testCMap0 = CMap0; - using VertexAttributeHandler = testCMap0::VertexAttributeHandler; + using VertexAttribute = testCMap0::VertexAttribute; using Vertex = testCMap0::Vertex; protected: @@ -94,6 +94,7 @@ TEST_F(CMap0Test, random_map_generators) TEST_F(CMap0Test, add_vertex) { add_vertices(NB_MAX); + EXPECT_EQ(cmap_.nb_cells(), NB_MAX); EXPECT_TRUE(cmap_.check_map_integrity()); } @@ -104,9 +105,15 @@ TEST_F(CMap0Test, remove_vertex) { add_vertices(NB_MAX); + uint32 count_vertices = NB_MAX; for (Dart d: darts_) - if (std::rand() % 3 == 1) cmap_.remove_vertex(Vertex(d)); + if (std::rand() % 3 == 1) + { + cmap_.remove_vertex(Vertex(d)); + --count_vertices; + } + EXPECT_EQ(cmap_.nb_cells(), count_vertices); EXPECT_TRUE(cmap_.check_map_integrity()); } diff --git a/cgogn/core/tests/cmap/cmap0_topo_test.cpp b/cgogn/core/tests/cmap/cmap0_topo_test.cpp index b2490dbe..58b3e896 100644 --- a/cgogn/core/tests/cmap/cmap0_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap0_topo_test.cpp @@ -23,7 +23,7 @@ #include -#include +#include namespace cgogn { @@ -76,7 +76,7 @@ class CMap0TopoTest : public ::testing::Test /*! * \brief The random generated maps used in the tests are sound. */ -TEST_F(CMap0TopoTest, Constructor) +TEST_F(CMap0TopoTest, random_map_generators) { EXPECT_EQ(cmap_.nb_darts(), 0u); @@ -84,6 +84,17 @@ TEST_F(CMap0TopoTest, Constructor) EXPECT_TRUE(cmap_.check_map_integrity()); } +/*! + * \brief Test attribute management + * + */ +TEST_F(CMap0TopoTest, add_attribute) +{ + add_vertices(NB_MAX); + cmap_.add_attribute("vertices"); + EXPECT_TRUE(cmap_.check_map_integrity()); +} + /*! * \brief Adding vertices adds one dart per vertex * and the map integrity is preserved @@ -110,12 +121,6 @@ TEST_F(CMap0TopoTest, remove_vertex) add_vertices(NB_MAX); int32 count_vertices = NB_MAX; - cmap_.remove_vertex(Vertex(darts_.back())); - --count_vertices; - EXPECT_EQ(cmap_.nb_darts(), count_vertices); - EXPECT_EQ(cmap_.nb_cells(), count_vertices); - - darts_.pop_back(); for (Dart d : darts_) { if (std::rand() % 3 == 1) diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index 6dd4c00e..3bd2c482 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -23,7 +23,7 @@ #include -#include +#include namespace cgogn { diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index 862d59cc..1a24a78e 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -23,7 +23,7 @@ #include -#include +#include namespace cgogn { @@ -109,6 +109,22 @@ TEST_F(CMap1TopoTest, random_map_generators) EXPECT_TRUE(check_map_integrity()); } +/*! + * \brief Test attribute management + * + */ +TEST_F(CMap1TopoTest, add_attribute) +{ + add_vertices(NB_MAX); + add_faces(NB_MAX); + + add_attribute("vertices"); + EXPECT_TRUE(check_map_integrity()); + + add_attribute("faces"); + EXPECT_TRUE(check_map_integrity()); +} + /*! * \brief Sewing and unsewing darts correctly changes the topological relations. * The test performs NB_MAX sewing and unsewing on randomly chosen dart of darts_. @@ -155,10 +171,10 @@ TEST_F(CMap1TopoTest, add_face_topo) EXPECT_EQ(nb_cells(), 2u); uint32 count_vertices = 11u + add_faces(NB_MAX); - EXPECT_EQ(nb_darts(), count_vertices); EXPECT_EQ(nb_cells(), count_vertices); EXPECT_EQ(nb_cells(), NB_MAX + 2u); + EXPECT_TRUE(check_map_integrity()); } @@ -166,7 +182,7 @@ TEST_F(CMap1TopoTest, add_face_topo) * The test randomly removes 1/3 of the initial faces. * The number of cells correctly decreases and the map integrity is preserved. */ -TEST_F(CMap1TopoTest, remove_face) +TEST_F(CMap1TopoTest, remove_face_topo) { uint32 count_vertices = add_faces(NB_MAX); uint32 count_faces = NB_MAX; @@ -177,7 +193,7 @@ TEST_F(CMap1TopoTest, remove_face) { Face f(d); uint32 k = codegree(f); - remove_face(f); + remove_face_topo(d); count_vertices -= k; --count_faces; } @@ -186,6 +202,7 @@ TEST_F(CMap1TopoTest, remove_face) EXPECT_EQ(nb_darts(), count_vertices); EXPECT_EQ(nb_cells(), count_vertices); EXPECT_EQ(nb_cells(), count_faces); + EXPECT_TRUE(check_map_integrity()); } @@ -204,9 +221,11 @@ TEST_F(CMap1TopoTest, split_vertex_topo) ++count_vertices; EXPECT_EQ(codegree(Face(d)), k + 1); } + EXPECT_EQ(nb_darts(), count_vertices); EXPECT_EQ(nb_cells(), count_vertices); EXPECT_EQ(nb_cells(), NB_MAX); + EXPECT_TRUE(check_map_integrity()); } @@ -214,7 +233,7 @@ TEST_F(CMap1TopoTest, split_vertex_topo) * The test performs NB_MAX vertex removing on vertices of randomly generated faces. * The number of removed cells is correct and the map integrity is preserved. */ -TEST_F(CMap1TopoTest, remove_vertex) +TEST_F(CMap1TopoTest, remove_vertex_topo) { uint32 count_vertices = add_faces(NB_MAX); uint32 count_faces = NB_MAX; @@ -225,20 +244,22 @@ TEST_F(CMap1TopoTest, remove_vertex) if (k > 1) { Dart e = phi1(d); - remove_vertex(Vertex(d)); + remove_vertex_topo(d); --count_vertices; EXPECT_EQ(codegree(Face(e)), k - 1); } else { - remove_vertex(Vertex(d)); + remove_vertex_topo(d); --count_faces; --count_vertices; } } + EXPECT_EQ(nb_darts(), count_vertices); EXPECT_EQ(nb_cells(), count_vertices); EXPECT_EQ(nb_cells(), count_faces); + EXPECT_TRUE(check_map_integrity()); } @@ -291,23 +312,48 @@ TEST_F(CMap1TopoTest, codegree) */ TEST_F(CMap1TopoTest, has_codegree) { - Face f(this->add_face_topo(10u)); + Face f1(this->add_face_topo(1u)); + + EXPECT_TRUE(has_codegree(f1, 1u)); + EXPECT_FALSE(has_codegree(f1, 0u)); + EXPECT_FALSE(has_codegree(f1, 2u)); + + Face f2(this->add_face_topo(2u)); + + EXPECT_TRUE(has_codegree(f2, 2u)); + EXPECT_FALSE(has_codegree(f2, 0u)); + EXPECT_FALSE(has_codegree(f2, 1u)); + EXPECT_FALSE(has_codegree(f2, 3u)); + + Face f3(this->add_face_topo(10u)); - EXPECT_TRUE(has_codegree(f, 10u)); - EXPECT_FALSE(has_codegree(f, 0u)); - EXPECT_FALSE(has_codegree(f, 9u)); - EXPECT_FALSE(has_codegree(f, 11u)); + EXPECT_TRUE(has_codegree(f3, 10u)); + EXPECT_FALSE(has_codegree(f3, 0u)); + EXPECT_FALSE(has_codegree(f3, 9u)); + EXPECT_FALSE(has_codegree(f3, 11u)); } /*! \brief The multi_phi are correctly applied */ TEST_F(CMap1TopoTest, multi_phi) { - Face f(this->add_face_topo(10u)); + Face f1(this->add_face_topo(1u)); + + EXPECT_EQ(f1.dart, this->phi<1>(f1.dart)); - EXPECT_EQ(f.dart, this->phi<1111111111>(f.dart)); + Face f2(this->add_face_topo(10u)); + + EXPECT_EQ(f2.dart, this->phi<1111111111>(f2.dart)); } +/*! \brief The number of connected components is correctly counted + */ +TEST_F(CMap1TopoTest, nb_connected_components) +{ + add_faces(NB_MAX); + + EXPECT_EQ(nb_connected_components(), NB_MAX); +} #undef NB_MAX diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index ba4eee83..dd5a2adf 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -23,7 +23,7 @@ #include -#include +#include namespace cgogn { @@ -44,8 +44,13 @@ class CMap2Test : public ::testing::Test public: - using testCMap2 = CMap2; - using MapBuilder = CMap2Builder_T; + struct MiniMapTraits + { + static const uint32 CHUNK_SIZE = 16; + }; + + using testCMap2 = CMap2; + using MapBuilder = CMap2Builder_T; using CDart = testCMap2::CDart; using Vertex = testCMap2::Vertex; using Edge = testCMap2::Edge; @@ -112,7 +117,7 @@ class CMap2Test : public ::testing::Test Dart d = mbuild.add_face_topo_parent(n); darts_.push_back(d); } - // Sew some pairs off edges + // Sew some pairs of edges for (uint32 i = 0u; i < 3u * NB_MAX; ++i) { Dart e1 = darts_[std::rand() % NB_MAX]; @@ -183,7 +188,6 @@ TEST_F(CMap2Test, add_face) EXPECT_EQ(cmap_.nb_cells(), count_vertices); EXPECT_EQ(cmap_.nb_cells(), count_vertices); EXPECT_EQ(cmap_.nb_cells(), NB_MAX); -// EXPECT_EQ(cmap_.nb_boundary_cells(), NB_MAX); EXPECT_EQ(cmap_.nb_cells(), NB_MAX); EXPECT_TRUE(cmap_.check_map_integrity()); } @@ -223,6 +227,140 @@ TEST_F(CMap2Test, cut_face) EXPECT_TRUE(cmap_.check_map_integrity()); } + +TEST_F(CMap2Test, compact_map) +{ + + testCMap2::VertexAttribute att_v = cmap_.get_attribute("vertices"); + testCMap2::EdgeAttribute att_e = cmap_.get_attribute("edges"); + testCMap2::FaceAttribute att_f = cmap_.get_attribute("faces"); + + for (int32 i=0; i<100; ++i) + { + Face f = cmap_.add_face(5); + int32 ec=0; + cmap_.foreach_incident_edge(f, [&] (Edge e) + { + ec++; + att_e[e]=100*i+ec; + att_v[Vertex(e.dart)]=1000*i+ec; + }); + att_f[i]=10*i; + darts_.push_back(f.dart); + } + + for (int32 i=0; i<100; i+=2) + { + Edge e(cmap_.phi1(darts_[i])); + cmap_.collapse_edge(e); + e = Edge(cmap_.phi1(darts_[i])); + cmap_.collapse_edge(e); + } + +// cmap_.foreach_cell([&] (Face f) +// { +// std::cout << "FACE:" <().size(), + cmap_.get_const_attribute_container().end()); + + EXPECT_EQ(cmap_.get_const_attribute_container().size(), + cmap_.get_const_attribute_container().end()); + + +// std::cout << "TOPO SIZE:"<< cmap_.get_topology_container().size() << " / END:"<< cmap_.get_topology_container().end() << std::endl; + +// std::cout << "VERT SIZE:"<< cmap_.get_attribute_container().size() << " / END:"<< cmap_.get_attribute_container().end() << std::endl; + + +// cmap_.foreach_cell([&] (Face f) +// { +// std::cout << "FACE:" < att1_v = map1.add_attribute("vertices"); + testCMap2::FaceAttribute att1_f = map1.add_attribute("faces"); + + testCMap2 map2; + testCMap2::Attribute att2_d = map2.add_attribute("darts"); + testCMap2::VertexAttribute att2_v = map2.add_attribute("vertices"); + testCMap2::EdgeAttribute att2_e = map2.add_attribute("edges"); + testCMap2::VolumeAttribute att2_w = map2.add_attribute("volumes"); + + for (int32 i=0; i<5; ++i) + { + Face f = map1.add_face(4); + int32 ec=0; + map1.foreach_incident_vertex(f, [&] (Vertex v) + { + ec++; + att1_v[v]=1000*i+ec; + }); + att1_f[i]=10*i; + } + + for (int32 i=0; i<5; ++i) + { + Face f = map2.add_face(3); + int32 ec=0; + map2.foreach_incident_edge(f, [&] (Edge e) + { + ec++; + att2_e[e]=100*i+ec; + }); + } + + map1.merge(map2); + + EXPECT_TRUE(map1.check_map_integrity()); + EXPECT_EQ(map1.nb_cells(),35); + EXPECT_EQ(map1.nb_cells(),35); + EXPECT_EQ(map1.nb_cells(),10); + EXPECT_EQ(map1.nb_cells(),10); + +} + #undef NB_MAX } // namespace cgogn diff --git a/cgogn/core/tests/cmap/cmap2_topo_test.cpp b/cgogn/core/tests/cmap/cmap2_topo_test.cpp index 0f437ff4..9e9c61f5 100644 --- a/cgogn/core/tests/cmap/cmap2_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_topo_test.cpp @@ -23,8 +23,8 @@ #include -#include -#include +#include +#include namespace cgogn { @@ -45,6 +45,7 @@ class CMap2TopoTest : public CMap2, public ::testing::Test using Inherit = CMap2; using MapBuilder = CMap2Builder_T; + using CDart = CMap2TopoTest::CDart; using Vertex = CMap2TopoTest::Vertex; using Edge = CMap2TopoTest::Edge; using Face = CMap2TopoTest::Face; @@ -203,6 +204,31 @@ TEST_F(CMap2TopoTest, random_map_generators) EXPECT_TRUE(check_map_integrity()); } +/*! + * \brief Test attribute management + * + */ +TEST_F(CMap2TopoTest, add_attribute) +{ + add_faces(NB_MAX); + add_closed_surfaces(); + + add_attribute("darts"); + EXPECT_TRUE(check_map_integrity()); + + add_attribute("vertices"); + EXPECT_TRUE(check_map_integrity()); + + add_attribute("edges"); + EXPECT_TRUE(check_map_integrity()); + + add_attribute("faces"); + EXPECT_TRUE(check_map_integrity()); + + add_attribute("Volumes"); + EXPECT_TRUE(check_map_integrity()); +} + /*! * \brief Sewing and unsewing darts correctly changes the topological relations. * The test performs NB_MAX sewing and unsewing on randomly chosen dart of darts_. @@ -252,11 +278,65 @@ TEST_F(CMap2TopoTest, add_face_topo) uint32 count_vertices = 11u + add_faces(NB_MAX); + for (Dart d : darts_) + EXPECT_TRUE(is_boundary(phi2(d))); + EXPECT_EQ(nb_darts(), 2u * count_vertices); EXPECT_EQ(nb_cells(), count_vertices); EXPECT_EQ(nb_cells(), count_vertices); EXPECT_EQ(nb_cells(), NB_MAX + 2u); EXPECT_EQ(nb_cells(), NB_MAX + 2u); + + EXPECT_TRUE(check_map_integrity()); +} + +/*! + * \brief Adding a pyramid whose base has n sides build a surface with + * 4*n darts, n+1 vertices, 2*n edges, n+1 faces and 1 volume. + * The test adds some pyramides and check that the number of generated cells is correct + * and that the map integrity is preserved. + */ +TEST_F(CMap2TopoTest, add_pyramid_topo) +{ + add_pyramid_topo(3u); + EXPECT_EQ(nb_darts(), 12u); + EXPECT_EQ(nb_cells(), 4u); + EXPECT_EQ(nb_cells(), 6u); + EXPECT_EQ(nb_cells(), 4u); + EXPECT_EQ(nb_cells(), 1u); + + add_pyramid_topo(10u); + EXPECT_EQ(nb_darts(), 40u+12u); + EXPECT_EQ(nb_cells(), 11+4u); + EXPECT_EQ(nb_cells(), 20u+6u); + EXPECT_EQ(nb_cells(), 11u+4u); + EXPECT_EQ(nb_cells(), 1u+1u); + + EXPECT_TRUE(check_map_integrity()); +} + +/*! + * \brief Adding a prism whose base has n sides build a surface with + * 4*n darts, n+1 vertices, 2*n edges, n+1 faces and 1 volume. + * The test adds some prims and check that the number of generated cells is correct + * and that the map integrity is preserved. + */ +TEST_F(CMap2TopoTest, add_prism_topo) +{ + add_prism_topo(3u); + EXPECT_EQ(nb_darts(), 18u); + EXPECT_EQ(nb_cells(), 6u); + EXPECT_EQ(nb_cells(), 9u); + EXPECT_EQ(nb_cells(), 5u); + EXPECT_EQ(nb_cells(), 1u); + + add_prism_topo(10u); + EXPECT_EQ(nb_darts(), 60u+18u); + EXPECT_EQ(nb_cells(), 20u+6u); + EXPECT_EQ(nb_cells(), 30u+9u); + EXPECT_EQ(nb_cells(), 12u+5u); + EXPECT_EQ(nb_cells(), 1u+1u); + EXPECT_TRUE(check_map_integrity()); } @@ -288,10 +368,108 @@ TEST_F(CMap2TopoTest, cut_edge_topo) EXPECT_EQ(codegree(Face(phi2(d))), k2 + 1u); } } + EXPECT_EQ(nb_cells(), count_vertices + NB_MAX); EXPECT_EQ(nb_cells(), count_edges + NB_MAX); EXPECT_EQ(nb_cells(), count_faces); EXPECT_EQ(nb_cells(), count_volumes); + + EXPECT_TRUE(check_map_integrity()); +} + +/*! \brief Fliping an edge changes the degree of its vertices. + * The test performs NB_MAX edge flips on randomly generated faces. + * The expected cells are modified and the map integrity is preserved. + */ +TEST_F(CMap2TopoTest, flip_edge_topo) +{ + add_closed_surfaces(); + + uint32 count_vertices = nb_cells(); + uint32 count_edges = nb_cells(); + uint32 count_faces = nb_cells(); + uint32 count_volumes = nb_cells(); + + for (Dart d : darts_) + { + Dart e1 = d; // choose a random edge in the face + uint32 i = std::rand() % 10u; + while (i-- > 0u) e1 = phi1(e1); + Dart e2 = phi2(e1); + + uint32 k1 = codegree(Face(e1)); + uint32 k2 = codegree(Face(e2)); + + Vertex k11_vertex = Vertex(e1); + Vertex k12_vertex = Vertex(phi1(phi1(e2))); + Vertex k21_vertex = Vertex(e2); + Vertex k22_vertex = Vertex(phi1(phi1(e1))); + + uint32 k11 = degree(k11_vertex); + uint32 k12 = degree(k12_vertex); + uint32 k21 = degree(k21_vertex); + uint32 k22 = degree(k22_vertex); + uint32* k11_ptr = &k11; + uint32* k12_ptr = &k12; + uint32* k21_ptr = &k21; + uint32* k22_ptr = &k22; + + // Handle special vertex configurations + if (same_cell(k11_vertex, k12_vertex)) k12_ptr = k11_ptr; + if (same_cell(k11_vertex, k21_vertex)) k21_ptr = k11_ptr; + if (same_cell(k11_vertex, k22_vertex)) k22_ptr = k11_ptr; + if (same_cell(k12_vertex, k21_vertex)) k21_ptr = k12_ptr; + if (same_cell(k12_vertex, k22_vertex)) k22_ptr = k12_ptr; + if (same_cell(k21_vertex, k22_vertex)) k22_ptr = k21_ptr; + + // Vertices with degree 1 do not move during an edge flip + bool k11_move = (degree(k11_vertex) > 1); + bool k21_move = (degree(k21_vertex) > 1); + + if (k11_move) + { + *k11_ptr -= 1u; + *k12_ptr += 1u; + } + if (k21_move) + { + *k21_ptr -= 1u; + *k22_ptr += 1u; + } + + if (flip_edge_topo(e1)) + { + EXPECT_EQ(codegree(Face(e1)), k1); + EXPECT_EQ(codegree(Face(e2)), k2); + + if (k11_move) + { + EXPECT_EQ(degree(Vertex(phi_1(e1))), *k11_ptr); + EXPECT_EQ(degree(Vertex(e1)), *k12_ptr); + } + else + { + EXPECT_EQ(degree(k11_vertex), *k11_ptr); + EXPECT_EQ(degree(k12_vertex), *k12_ptr); + } + if (k21_move) + { + EXPECT_EQ(degree(Vertex(phi_1(e2))), *k21_ptr); + EXPECT_EQ(degree(Vertex(e2)), *k22_ptr); + } + else + { + EXPECT_EQ(degree(k21_vertex), *k21_ptr); + EXPECT_EQ(degree(k22_vertex), *k22_ptr); + } + } + } + + EXPECT_EQ(nb_cells(), count_vertices); + EXPECT_EQ(nb_cells(), count_edges); + EXPECT_EQ(nb_cells(), count_faces); + EXPECT_EQ(nb_cells(), count_volumes); + EXPECT_TRUE(check_map_integrity()); } @@ -312,9 +490,6 @@ TEST_F(CMap2TopoTest, cut_face_topo) for (Dart d : darts_) { Dart dd = d; - if (std::rand() % 2 == 1) dd = phi2(d); - - bool boundary_face = is_boundary(dd); uint32 k = codegree(Face(dd)); if (k > 1u) @@ -325,18 +500,18 @@ TEST_F(CMap2TopoTest, cut_face_topo) if (e == dd) e = phi1(e); cut_face_topo(dd, e); + ++count_edges; + ++count_faces; - if (!boundary_face) { - ++count_edges; - ++count_faces; - } EXPECT_EQ(codegree(Face(dd)) + codegree(Face(e)), k + 2); } } + EXPECT_EQ(nb_cells(), count_vertices); EXPECT_EQ(nb_cells(), count_edges); EXPECT_EQ(nb_cells(), count_faces); EXPECT_EQ(nb_cells(), count_volumes); + EXPECT_TRUE(check_map_integrity()); } @@ -403,14 +578,26 @@ TEST_F(CMap2TopoTest, close_map) MapBuilder mbuild(*this); mbuild.close_map(); + EXPECT_TRUE(check_map_integrity()); } TEST_F(CMap2TopoTest, degree) { - Face f(this->add_face_topo(10u)); - - EXPECT_EQ(codegree(f), 10u); + Face f1(this->add_face_topo(1u)); + EXPECT_EQ(codegree(Edge(f1.dart)), 1u); + EXPECT_EQ(degree(Edge(f1.dart)), 1u); + EXPECT_EQ(degree(f1), 1u); + + Face f2(this->add_face_topo(10u)); + EXPECT_EQ(codegree(Edge(f2.dart)), 2u); + EXPECT_EQ(degree(Edge(f2.dart)), 1u); + + phi2_unsew(f1.dart); + phi2_unsew(f2.dart); + phi2_sew(f1.dart, f2.dart); + EXPECT_EQ(degree(Edge(f1.dart)), 2u); + EXPECT_EQ(degree(Edge(f2.dart)), 2u); } @@ -426,6 +613,18 @@ TEST_F(CMap2TopoTest, multi_phi) EXPECT_EQ(f.dart, this->phi<11122111221111>(f.dart)); } +/*! \brief The number of connected components is correctly counted + */ +TEST_F(CMap2TopoTest, nb_connected_components) +{ + add_faces(10u); + add_prism_topo(3u); + add_prism_topo(5u); + add_pyramid_topo(4u); + + EXPECT_EQ(nb_connected_components(), 13u); +} + #undef NB_MAX } // namespace cgogn diff --git a/cgogn/core/tests/cmap/cmap3_topo_test.cpp b/cgogn/core/tests/cmap/cmap3_topo_test.cpp index b1fe4f8b..129fc89a 100644 --- a/cgogn/core/tests/cmap/cmap3_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap3_topo_test.cpp @@ -23,12 +23,14 @@ #include -#include -#include +#include +#include namespace cgogn { +#define NB_MAX 1000 + /*! * \brief The CMap3TopoTest class implements topological tests on CMap3 * It derives from CMap3 to allow the test of protected methods @@ -44,51 +46,352 @@ class CMap3TopoTest : public CMap3, public ::testing::Test using Inherit = CMap3; using MapBuilder = CMap3Builder_T; + using Vertex2 = CMap3TopoTest::Vertex2; using Vertex = CMap3TopoTest::Vertex; + using Edge2 = CMap3TopoTest::Edge2; using Edge = CMap3TopoTest::Edge; + using Face2 = CMap3TopoTest::Face2; using Face = CMap3TopoTest::Face; using Volume = CMap3TopoTest::Volume; using VertexMarker = CMap3TopoTest::CellMarker; protected: + /*! + * \brief A vector of darts on which the methods are tested. + */ + std::vector darts_; + + /*! + * \brief Generate a random set of faces. + */ + CMap3TopoTest() + { + darts_.reserve(NB_MAX); + std::srand(static_cast(std::time(0))); + } + + /*! + * \brief Tests if the open vertex of d contains a specified dart e. + * The method supposes that the given dart d is the first dart + * of the open PHI21 orbit (i.e. phi2(d) == d) + */ + bool same_open_vertex(Dart d, Dart e) + { + cgogn_assert(phi2(d) == d); + Dart it = d; + Dart it1 = phi_1(it); + + while (it != e && phi2(it1) != it1) + { + it = phi2(it1); + it1 = phi_1(it); + } + if (it == e) return true; + return false; + } + + /*! + * \brief Tests if the volume of d contains a specified dart e. + * The method does not exploit the indexing information + */ + bool same_volume(Dart d, Dart e) + { + bool result = false; + + foreach_dart_of_orbit_until(Volume(d), [&](Dart vit) + { + if (vit == e) result = true; + return !result; + }); + + return result; + } + + /*! + * \brief Embed an open vertex d on a new attribute. + * The method supposes that the given dart d is the first dart + * of the open PHI21 orbit (i.e. phi2(d) == d) + */ + void new_open_vertex_embedding(Dart d) + { + cgogn_assert(phi2(d) == d); + const unsigned int emb = add_attribute_element(); + + Dart it = d; + Dart it1 = phi_1(it); + set_embedding(it, emb); + while (phi2(it1) != it1) + { + it = phi2(it1); + it1 = phi_1(it); + set_embedding(it, emb); + } + } + + /*! + * \brief Generate a set of closed surfaces with arbitrary genus. + */ + void add_closed_surfaces() + { + darts_.clear(); + + // Generate NB_MAX random 2-surfaces (without boundary + for (unsigned int i = 0u; i < NB_MAX; ++i) + { + uint32 n = 1u + std::rand() % 10; + uint32 p = std::rand() % 2; + switch (p) { + case 0: + darts_.push_back(Inherit::add_pyramid_topo(n)); + break; + case 1: + darts_.push_back(Inherit::add_prism_topo(n)); + break; + default: + break; + } + + } + + // Close de map + MapBuilder mbuild(*this); + mbuild.close_map(); + } }; /*! - * \brief Test pyramid creation. + * \brief The random generated maps used in the tests are sound. */ -TEST_F(CMap3TopoTest, pyramid_test) +TEST_F(CMap3TopoTest, random_map_generators) { - Dart d1 = this->add_pyramid_topo(4); - CMap3TopoTest::MapBuilder mbuild(*this); - mbuild.close_map(); + EXPECT_EQ(nb_darts(), 0u); + add_closed_surfaces(); + EXPECT_TRUE(check_map_integrity()); +} + +/*! + * \brief Test attribute management + * + */ +TEST_F(CMap3TopoTest, add_attribute) +{ + add_closed_surfaces(); + add_attribute("darts"); EXPECT_TRUE(check_map_integrity()); - EXPECT_EQ(nb_darts(), 32u); - Dart d2 = this->phi<32121213>(d1); - EXPECT_EQ(d1,d2); -} + add_attribute("vertices2"); + EXPECT_TRUE(check_map_integrity()); + + add_attribute("vertices"); + EXPECT_TRUE(check_map_integrity()); + + add_attribute("edges2"); + EXPECT_TRUE(check_map_integrity()); + add_attribute("edges"); + EXPECT_TRUE(check_map_integrity()); + + add_attribute("faces2"); + EXPECT_TRUE(check_map_integrity()); + + add_attribute("faces"); + EXPECT_TRUE(check_map_integrity()); + + add_attribute("Volumes"); + EXPECT_TRUE(check_map_integrity()); +} /*! - * \brief Test pyramid creation. + * \brief Sewing and unsewing darts correctly changes the topological relations. + * The test performs NB_MAX sewing and unsewing on randomly chosen dart of darts_. + * The map integrity is not preserved (this test creates fixed points for PHI3). */ -TEST_F(CMap3TopoTest, prism_test) +TEST_F(CMap3TopoTest, phi3_sew_unsew) { - Dart d1 = this->add_prism_topo(3); - CMap3TopoTest::MapBuilder mbuild(*this); - mbuild.close_map(); + add_closed_surfaces(); - EXPECT_TRUE(check_map_integrity()); - EXPECT_EQ(nb_darts(), 36u); + for (unsigned int i = 0u; i < NB_MAX; ++i) + { + Dart d0 = darts_[std::rand() % NB_MAX]; + Dart d3 = phi3(d0); + phi3_unsew(d0); + EXPECT_TRUE(phi3(d0) == d0); + EXPECT_TRUE(phi3(d3) == d3); + Dart e0 = d0; + while (e0 == d0) e0 = darts_[std::rand() % NB_MAX]; + phi3_unsew(e0); + + phi3_sew(d0, e0); + EXPECT_TRUE(phi3(d0) == e0); + EXPECT_TRUE(phi3(e0) == d0); + } +} + +/*! \brief Cutting an edge increases the size of both incident faces and add a vertex of degree 2. + * The test performs NB_MAX edge cutting on edges of randomly generated faces. + * The number of generated cells is correct and the map integrity is preserved. + */ +TEST_F(CMap3TopoTest, cut_edge_topo) +{ +// add_closed_surfaces(); + +// unsigned int count_vertices = nb_cells(); +// unsigned int count_edges = nb_cells(); +// unsigned int count_faces = nb_cells(); +// unsigned int count_volumes = nb_cells(); + +// for (Dart d : darts_) +// { +// unsigned int k1 = degree(Face(d)); +// unsigned int k2 = degree(Face(phi2(d))); +// cut_edge_topo(d); +// if (same_cell(Face(d), Face(phi2(d)))) +// { +// EXPECT_EQ(degree(Face(d)), k1 + 2u); +// } +// else +// { +// EXPECT_EQ(degree(Face(d)), k1 + 1u); +// EXPECT_EQ(degree(Face(phi2(d))), k2 + 1u); +// } +// } +// EXPECT_EQ(nb_cells(), count_vertices + NB_MAX); +// EXPECT_EQ(nb_cells(), count_edges + NB_MAX); +// EXPECT_EQ(nb_cells(), count_faces); +// EXPECT_EQ(nb_cells(), count_volumes); +// EXPECT_TRUE(check_map_integrity()); +} - d1 = this->phi<321>(d1); - Dart d2 = this->phi<112112112>(d1); - EXPECT_EQ(d1,d2); +/*! \brief Cutting a face add an edge and replace a face of degree K, + * with two subfaces whose degrees K1 and K2 verify K1+K2 = K+2. + * The test performs NB_MAX face cuts between vertices of a randomly generated surface. + * The number of generated cells is correct and the map integrity is preserved. + */ +TEST_F(CMap3TopoTest, cut_face_topo) +{ +// add_closed_surfaces(); + +// unsigned int count_vertices = nb_cells(); +// unsigned int count_edges = nb_cells(); +// unsigned int count_faces = nb_cells(); +// unsigned int count_volumes = nb_cells(); + +// for (Dart d : darts_) +// { +// unsigned int k = degree(Face(d)); +// if (k > 1u) +// { +// Dart e = d; // find a second dart in the face of d (distinct from d) +// unsigned int i = std::rand() % 10u; +// while (i-- > 0u) e = phi1(e); +// if (e == d) e = phi1(e); + +// cut_face_topo(d, e); +// ++count_edges; +// ++count_faces; +// EXPECT_EQ(degree(Face(d)) + degree(Face(e)), k + 2); +// } +// } +// EXPECT_EQ(nb_cells(), count_vertices); +// EXPECT_EQ(nb_cells(), count_edges); +// EXPECT_EQ(nb_cells(), count_faces); +// EXPECT_EQ(nb_cells(), count_volumes); +// EXPECT_TRUE(check_map_integrity()); } +/*! \brief Closing a map add one face per holes. + * The test closes the holes of a randomly generated open surface. + * The map integrity is preserved and the cell indexation is soundly completed + */ +TEST_F(CMap3TopoTest, close_map) +{ +// add_closed_surfaces(); + +// // add attributes to initialize the indexation +// add_attribute("darts"); +// add_attribute("vertices"); +// add_attribute("edges"); +// add_attribute("faces"); +// add_attribute("volumes"); +// EXPECT_TRUE(check_map_integrity()); + +// // create some random holes (full removal or partial unsewing of faces) +// for (Dart d : darts_) +// { +// if (std::rand() % 2 == 1) +// { +// unsigned int n = std::rand() % 10u; +// unsigned int k = degree(Face(d)); + +// foreach_dart_of_orbit_until(Face(d), [&] (Dart e) +// { +// Dart e2 = phi2(e); +// phi2_unsew(e); +// // correct indexation of vertices +// if (!same_open_vertex(e2, phi1(e))) new_open_vertex_embedding(e2); +// if (!same_open_vertex(e, phi1(e2))) new_open_vertex_embedding(e); +// // correct indexation of edges +// new_orbit_embedding(Edge(e2)); +// // correct indexation of volumes +// if (!same_volume(e2, e)) new_orbit_embedding(Volume(e)); +// // interrupt the face unsewing after n steps +// if (n-- <= 0) return false; +// // control if a partial or full face unsewing has been done +// --k; +// return true; +// }); +// // if the face is completely unsewn randomly removes it +// if (k == 0u && std::rand() % 2 == 1) +// { +// Dart e = d; +// Dart it = phi1(e); +// while (it != e) +// { +// Dart next = phi1(it); +// this->remove_dart(it); +// it = next; +// } +// this->remove_dart(e); +// } +// } +// } + +// MapBuilder mbuild(*this); +// mbuild.close_map(); +// EXPECT_TRUE(check_map_integrity()); +} + +TEST_F(CMap3TopoTest, degree) +{ +// Face f(this->add_face_topo(10u)); + +// EXPECT_EQ(degree(f), 10u); +} + +/*! \brief The number of connected components is correctly counted + */ +TEST_F(CMap3TopoTest, nb_connected_components) +{ + MapBuilder mbuild(*this); + + Dart p1 = add_prism_topo(3u); + Dart p2 = add_prism_topo(3u); + mbuild.sew_volumes(Volume(p1), Volume(p2)); + + Dart p3 = add_pyramid_topo(4u); + Dart p4 = add_pyramid_topo(4u); + mbuild.sew_volumes(Volume(p3), Volume(p4)); + + add_prism_topo(5u); + + mbuild.close_map(); + + EXPECT_EQ(nb_connected_components(), 3u); +} +#undef NB_MAX } // namespace cgogn diff --git a/cgogn/core/tests/container/chunk_array_container_test.cpp b/cgogn/core/tests/container/chunk_array_container_test.cpp index 1ddceb13..63f9853c 100644 --- a/cgogn/core/tests/container/chunk_array_container_test.cpp +++ b/cgogn/core/tests/container/chunk_array_container_test.cpp @@ -23,16 +23,20 @@ #include -#include +#include namespace cgogn { class ChunkArrayContainerTest : public ::testing::Test { -protected: +//protected: +public: - ChunkArrayContainerTest() + using ChunkArrayContainer = cgogn::ChunkArrayContainer<16u,uint32> ; + template using ChunkArray = cgogn::ChunkArray<16u, T>; + + ChunkArrayContainerTest() {} // @@ -53,4 +57,351 @@ TEST_F(ChunkArrayContainerTest, testAddAttribute) this->testAddAttribute(); } +TEST_F(ChunkArrayContainerTest, testRemove) +{ + ChunkArrayContainer ca_cont; + + for (uint32 i=0; i<40; ++i) + ca_cont.insert_lines<1>(); + + EXPECT_EQ(ca_cont.size(),40); + + ca_cont.remove_lines<1>(3); + ca_cont.remove_lines<1>(19); + ca_cont.remove_lines<1>(37); + + EXPECT_EQ(ca_cont.size(),37); + + uint32 i1 = ca_cont.insert_lines<1>(); + uint32 i2 = ca_cont.insert_lines<1>(); + uint32 i3 = ca_cont.insert_lines<1>(); + + EXPECT_EQ(ca_cont.size(),40); + + EXPECT_EQ(i1,37); + EXPECT_EQ(i2,19); + EXPECT_EQ(i3,3); +} + +TEST_F(ChunkArrayContainerTest, test_compact) +{ + using DATA = uint32; + ChunkArrayContainer ca_cont; + ChunkArray* indices = ca_cont.add_attribute("indices"); + + for (uint32 i=0; i<20; ++i) + { + ca_cont.insert_lines<1>(); + indices->operator [](i) = i; + } + + ca_cont.remove_lines<1>(0); + ca_cont.remove_lines<1>(18); + ca_cont.remove_lines<1>(2); + ca_cont.remove_lines<1>(17); + ca_cont.remove_lines<1>(3); + ca_cont.remove_lines<1>(15); + ca_cont.remove_lines<1>(5); + ca_cont.remove_lines<1>(6); + ca_cont.remove_lines<1>(7); + ca_cont.remove_lines<1>(9); + ca_cont.remove_lines<1>(10); + ca_cont.remove_lines<1>(11); + ca_cont.remove_lines<1>(13); + ca_cont.remove_lines<1>(14); + + EXPECT_EQ(ca_cont.size(),6); + + std::vector old_new = ca_cont.compact<1>(); + EXPECT_EQ(old_new.size(),20); + + EXPECT_EQ(ca_cont.size(),6); + +// for (uint32 i=ca_cont.begin(); i!=ca_cont.end(); ca_cont.next(i)) +// std::cout << i << " => "<operator [](i)<< std::endl; + + std::vector after; + for (uint32 i=ca_cont.begin(); i!=ca_cont.end(); ca_cont.next(i)) + after.push_back(indices->operator [](i)); + + auto contains = [&] (DATA x) -> bool { return std::find(after.begin(),after.end(),x) != after.end(); }; + + EXPECT_TRUE( contains(1) ); + EXPECT_TRUE( contains(4) ); + EXPECT_TRUE( contains(8) ); + EXPECT_TRUE( contains(12) ); + EXPECT_TRUE( contains(16) ); + EXPECT_TRUE( contains(19) ); + +// uint32 i=0; +// for(uint32 x: old_new) +// std::cout << i++ << " : "<< x << std::endl; + +} + +TEST_F(ChunkArrayContainerTest, test_compact_tri) +{ + using DATA = uint32; + + ChunkArrayContainer ca_cont; + + + ChunkArray* indices = ca_cont.add_attribute("indices"); + + for (uint32 i=0; i<10; ++i) + { + ca_cont.insert_lines<3>(); + indices->operator [](i) = i; + } + + for (uint32 i=0; i<30; ++i) + { + indices->operator [](i) = i; + } + + + ca_cont.remove_lines<3>(0); + ca_cont.remove_lines<3>(8*3); + ca_cont.remove_lines<3>(2*3); + ca_cont.remove_lines<3>(6*3); + ca_cont.remove_lines<3>(4*3); + + EXPECT_EQ(ca_cont.size(),15); + + std::vector old_new = ca_cont.compact<3>(); + EXPECT_EQ(old_new.size(),30); + + EXPECT_EQ(ca_cont.size(),15); + +// for (uint32 i=ca_cont.begin(); i!=ca_cont.end(); ca_cont.next(i)) +// std::cout << i << " => "<operator [](i)<< std::endl; + + std::vector after; + for (uint32 i=ca_cont.begin(); i!=ca_cont.end(); ca_cont.next(i)) + after.push_back(indices->operator [](i)); + + auto contains = [&] (DATA x) -> bool { return std::find(after.begin(),after.end(),x) != after.end(); }; + + EXPECT_TRUE( contains(3) ); + EXPECT_TRUE( contains(4) ); + EXPECT_TRUE( contains(5) ); + EXPECT_TRUE( contains(9) ); + EXPECT_TRUE( contains(10) ); + EXPECT_TRUE( contains(11) ); + EXPECT_TRUE( contains(15) ); + EXPECT_TRUE( contains(16) ); + EXPECT_TRUE( contains(17) ); + EXPECT_TRUE( contains(21) ); + EXPECT_TRUE( contains(22) ); + EXPECT_TRUE( contains(23) ); + EXPECT_TRUE( contains(27) ); + EXPECT_TRUE( contains(28) ); + EXPECT_TRUE( contains(29) ); + +// uint32 i=0; +// for(uint32 x: old_new) +// std::cout << i++ << " : "<< x << std::endl; + +} + + +TEST_F(ChunkArrayContainerTest, test_merge) +{ + using VEC3F = std::array; + ChunkArrayContainer::ChunkArrayFactory::register_known_types(); + + ChunkArrayContainer ca_cont; + ChunkArray* data_i = ca_cont.add_attribute("indices"); + ChunkArray* data_f = ca_cont.add_attribute("data_f"); + + ChunkArrayContainer ca_cont2; + ChunkArray* data2_v = ca_cont2.add_attribute("data_v"); + ChunkArray* data2_i16 = ca_cont2.add_attribute("indices"); + + // test impossible merge + bool ok = ca_cont.check_before_merge(ca_cont2); + EXPECT_FALSE(ok); + + // correct attribute + ca_cont2.remove_attribute(data2_i16); + ChunkArray* data2_i = ca_cont2.add_attribute("indices"); + + // filling + for (uint32 i=0; i<10; ++i) + { + ca_cont.insert_lines<1>(); + data_i->operator [](i) = i; + data_f->operator [](i) = 0.01f*i; + } + ca_cont.remove_lines<1>(2); + ca_cont.remove_lines<1>(4); + ca_cont.remove_lines<1>(7); + + for (uint32 i=0; i<10; ++i) + { + ca_cont2.insert_lines<1>(); + data2_i->operator [](i) = 100+i; + float32 x = 100.0f+0.01f*i; + data2_v->operator [](i) = {{x,x,x}}; + } + ca_cont2.remove_lines<1>(3); + ca_cont2.remove_lines<1>(6); + ca_cont2.remove_lines<1>(9); + + + //testing + ok = ca_cont.check_before_merge(ca_cont2); + EXPECT_TRUE(ok); + + if (!ok) + return; + + std::vector old_new = ca_cont.merge<1>(ca_cont2); + EXPECT_EQ(old_new.size(),9); + EXPECT_EQ(ca_cont.size(),14); + +// std::cout << "=============================" << std::endl; +// ChunkArray* data_v = ca_cont.get_attribute("data_v"); +// for (uint32 i=ca_cont.begin(); i!=ca_cont.end(); ca_cont.next(i)) +// { +// std::cout << i << " => "; +// std::cout << data_i->operator [](i) <<" / "; +// std::cout << data_f->operator [](i) <<" / "; +// const VEC3F& X= data_v->operator [](i); +// std::cout << X[0]<< "," << X[1]<< "," << X[2]; +// std::cout << std::endl; +// } +// std::cout << "=============================" << std::endl; +// uint32 i=0; +// for(uint32 x: old_new) +// std::cout << i++ << " : "<< x << std::endl; + + // check contains of result + std::vector after; + for (uint32 i=ca_cont.begin(); i!=ca_cont.end(); ca_cont.next(i)) + after.push_back(data_i->operator [](i)); + + auto contains = [&] (uint32 x) -> bool { return std::find(after.begin(),after.end(),x) != after.end(); }; + + EXPECT_EQ(after.size(),14); + EXPECT_TRUE( contains(0) ); + EXPECT_TRUE( contains(1) ); + EXPECT_TRUE( contains(3) ); + EXPECT_TRUE( contains(5) ); + EXPECT_TRUE( contains(6) ); + EXPECT_TRUE( contains(8) ); + EXPECT_TRUE( contains(9) ); + EXPECT_TRUE( contains(100) ); + EXPECT_TRUE( contains(101) ); + EXPECT_TRUE( contains(102) ); + EXPECT_TRUE( contains(104) ); + EXPECT_TRUE( contains(105) ); + EXPECT_TRUE( contains(107) ); + EXPECT_TRUE( contains(108) ); + +} + + + +TEST_F(ChunkArrayContainerTest, test_merge_tri) +{ + using VEC3F = std::array; + + ChunkArrayContainer::ChunkArrayFactory::register_known_types(); + + ChunkArrayContainer ca_cont; + ChunkArray* data_i = ca_cont.add_attribute("indices"); + ChunkArray* data_f = ca_cont.add_attribute("data_f"); + + ChunkArrayContainer ca_cont2; + ChunkArray* data2_v = ca_cont2.add_attribute("data_v"); + ChunkArray* data2_i = ca_cont2.add_attribute("indices"); + ChunkArray* data2_b = ca_cont2.add_attribute("booleens"); + + for (uint32 i=0; i<3; ++i) + ca_cont.insert_lines<3>(); + + for (uint32 i=0; i<9; ++i) + { + data_i->operator [](i) = i; + data_f->operator [](i) = 0.01f*i; + } + + ca_cont.remove_lines<3>(4); + + for (uint32 i=0; i<3; ++i) + ca_cont2.insert_lines<3>(); + + for (uint32 i=0; i<9; ++i) + { + data2_i->operator [](i) = 100+i; + float32 x = 100.0f+0.01f*i; + data2_v->operator [](i) = {{x,x,x}}; + data2_b->operator [](i) = true; + } + + ca_cont2.remove_lines<3>(5); + + bool ok = ca_cont.check_before_merge(ca_cont2); + EXPECT_TRUE(ok); + + if (!ok) + return; + + std::vector old_new = ca_cont.merge<3>(ca_cont2); + + EXPECT_EQ(old_new.size(),9); + EXPECT_EQ(ca_cont.size(),12); + + ChunkArray* data_b = ca_cont.get_attribute("booleens"); + + // ChunkArray* data_v = ca_cont.get_attribute("data_v"); +// std::cout << "=============================" << std::boolalpha< "; +// std::cout << data_i->operator [](i) <<" / "; +// std::cout << data_f->operator [](i) <<" / "; +// const VEC3F& X= data_v->operator [](i); +// std::cout << X[0]<< "," << X[1]<< "," << X[2] << " / " << data_b->operator [](i); +// std::cout << std::endl; +// } +// std::cout << "=============================" << std::endl; +// uint32 i=0; +// for(uint32 x: old_new) +// std::cout << i++ << " : "<< x << std::endl; + + + + // check contains of result + std::vector after; + uint32 nb_true=0u; + for (uint32 i=ca_cont.begin(); i!=ca_cont.end(); ca_cont.next(i)) + { + after.push_back(data_i->operator [](i)); + if (data_b->operator [](i)) + nb_true++; + } + + auto contains = [&] (uint32 x) -> bool { return std::find(after.begin(),after.end(),x) != after.end(); }; + + EXPECT_EQ(after.size(),12); + EXPECT_EQ(nb_true,6); + EXPECT_TRUE( contains(0) ); + EXPECT_TRUE( contains(1) ); + EXPECT_TRUE( contains(2) ); + EXPECT_TRUE( contains(6) ); + EXPECT_TRUE( contains(7) ); + EXPECT_TRUE( contains(8) ); + EXPECT_TRUE( contains(100) ); + EXPECT_TRUE( contains(101) ); + EXPECT_TRUE( contains(102) ); + EXPECT_TRUE( contains(106) ); + EXPECT_TRUE( contains(107) ); + EXPECT_TRUE( contains(108) ); + +} + + + } // namespace cgogn diff --git a/cgogn/core/tests/utils/name_types_test.cpp b/cgogn/core/tests/utils/name_types_test.cpp index 21391be1..33f953a4 100644 --- a/cgogn/core/tests/utils/name_types_test.cpp +++ b/cgogn/core/tests/utils/name_types_test.cpp @@ -21,8 +21,8 @@ * * *******************************************************************************/ -#include -#include +#include +#include #include @@ -53,13 +53,13 @@ TEST(NameTypesTest, NumTypes) EXPECT_EQ(cgogn::name_of_type(int64()), "int64"); EXPECT_EQ(cgogn::name_of_type(uint64()), "uint64"); - EXPECT_EQ(cgogn::name_of_type(float()), "float"); - EXPECT_EQ(cgogn::name_of_type(double()), "double"); + EXPECT_EQ(cgogn::name_of_type(float()), "float32"); + EXPECT_EQ(cgogn::name_of_type(double()), "float64"); EXPECT_EQ(cgogn::name_of_type(std::string()), "std::basic_string"); - EXPECT_EQ(cgogn::name_of_type(std::vector()), "std::vector"); - EXPECT_EQ(cgogn::name_of_type(std::vector>()), "std::vector>"); - EXPECT_EQ(cgogn::name_of_type(std::array()), "std::array"); + EXPECT_EQ(cgogn::name_of_type(std::vector()), "std::vector"); + EXPECT_EQ(cgogn::name_of_type(std::vector>()), "std::vector>"); + EXPECT_EQ(cgogn::name_of_type(std::array()), "std::array"); EXPECT_EQ(cgogn::name_of_type(cgogn::Dart()), "cgogn::Dart"); EXPECT_EQ(cgogn::name_of_type(cgogn::Cell()), "cgogn::Cell"); diff --git a/cgogn/core/utils/assert.cpp b/cgogn/core/utils/assert.cpp index 27469957..e0c5a2aa 100644 --- a/cgogn/core/utils/assert.cpp +++ b/cgogn/core/utils/assert.cpp @@ -23,8 +23,8 @@ #define CGOGN_CORE_DLL_EXPORT -#include -#include +#include +#include #include #include #include diff --git a/cgogn/core/utils/assert.h b/cgogn/core/utils/assert.h index 44f95d84..f56a5342 100644 --- a/cgogn/core/utils/assert.h +++ b/cgogn/core/utils/assert.h @@ -21,14 +21,14 @@ * * *******************************************************************************/ -#ifndef CORE_UTILS_ASSERT_H_ -#define CORE_UTILS_ASSERT_H_ +#ifndef CGOGN_CORE_UTILS_ASSERT_H_ +#define CGOGN_CORE_UTILS_ASSERT_H_ #include #include -#include -#include +#include +#include #if defined (WIN32) && !defined(__func__) #define __func__ __FUNCTION__ @@ -228,6 +228,7 @@ struct function_traits template struct arg { + static_assert(i < sizeof...(Args) ,"Trying to access to an argument whose index is higher than the function arity."); using type = typename std::tuple_element>::type; // the i-th argument is equivalent to the i-th tuple element of a tuple // composed of those arguments. @@ -243,4 +244,4 @@ struct function_traits #define inside_type(ATTR) typename std::remove_cv::type>::type -#endif // CORE_UTILS_ASSERT_H_ +#endif // CGOGN_CORE_UTILS_ASSERT_H_ diff --git a/cgogn/core/utils/buffers.h b/cgogn/core/utils/buffers.h index 8ba1a051..f750fa83 100644 --- a/cgogn/core/utils/buffers.h +++ b/cgogn/core/utils/buffers.h @@ -21,15 +21,15 @@ * * *******************************************************************************/ -#ifndef CORE_UTILS_BUFFERS_H_ -#define CORE_UTILS_BUFFERS_H_ +#ifndef CGOGN_CORE_UTILS_BUFFERS_H_ +#define CGOGN_CORE_UTILS_BUFFERS_H_ #include #include -#include -#include -#include +#include +#include +#include namespace cgogn { @@ -152,4 +152,4 @@ class Buffers } // namespace cgogn -#endif // CORE_UTILS_BUFFERS_H_ +#endif // CGOGN_CORE_UTILS_BUFFERS_H_ diff --git a/cgogn/core/utils/definitions.h b/cgogn/core/utils/definitions.h index d88b2b89..ef72b2c9 100644 --- a/cgogn/core/utils/definitions.h +++ b/cgogn/core/utils/definitions.h @@ -21,35 +21,8 @@ * * *******************************************************************************/ -#ifndef CORE_UTILS_DEFINITIONS_H_ -#define CORE_UTILS_DEFINITIONS_H_ - - -#include - -namespace cgogn -{ - -namespace numerics -{ - -using int8 = std::int8_t; -using int16 = std::int16_t; -using int32 = std::int32_t; -using int64 = std::int64_t; - -using uint8 = std::uint8_t; -using uint16 = std::uint16_t; -using uint32 = std::uint32_t; -using uint64 = std::uint64_t; - -using float32 = float; -using float64 = double; - -} - -using namespace numerics; -} +#ifndef CGOGN_CORE_UTILS_DEFINITIONS_H_ +#define CGOGN_CORE_UTILS_DEFINITIONS_H_ /** * \brief No execpt declaration for CGOGN symbols. @@ -153,7 +126,6 @@ using namespace numerics; _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ _Pragma("clang diagnostic ignored \"-Wdeprecated\"") \ _Pragma("clang diagnostic ignored \"-Wsign-conversion\"") \ - _Pragma("clang diagnostic ignored \"-Wreserved-id-macro\"") \ _Pragma("clang diagnostic ignored \"-Wshadow\"") \ _Pragma("clang diagnostic ignored \"-Wmissing-noreturn\"") \ _Pragma("clang diagnostic ignored \"-Wused-but-marked-unused\"") @@ -177,4 +149,4 @@ using namespace numerics; CLASSNAME& operator=(const CLASSNAME&) = delete;\ CLASSNAME& operator=(CLASSNAME&&) = delete -#endif // CORE_UTILS_DEFINITIONS_H_ +#endif // CGOGN_CORE_UTILS_DEFINITIONS_H_ diff --git a/cgogn/core/utils/endian.h b/cgogn/core/utils/endian.h index 2b4c4a81..eaa70b8b 100644 --- a/cgogn/core/utils/endian.h +++ b/cgogn/core/utils/endian.h @@ -21,12 +21,12 @@ * * *******************************************************************************/ -#ifndef CORE_UTILS_ENDIAN_H_ -#define CORE_UTILS_ENDIAN_H_ +#ifndef CGOGN_CORE_UTILS_ENDIAN_H_ +#define CGOGN_CORE_UTILS_ENDIAN_H_ #include #include -#include +#include namespace cgogn { @@ -222,4 +222,4 @@ inline T swap_endianness_native_little(T x) } // namespace cgogn -#endif // CORE_UTILS_ENDIAN_H_ +#endif // CGOGN_CORE_UTILS_ENDIAN_H_ diff --git a/cgogn/core/utils/log_entry.cpp b/cgogn/core/utils/log_entry.cpp index 5179d8b1..2e473395 100644 --- a/cgogn/core/utils/log_entry.cpp +++ b/cgogn/core/utils/log_entry.cpp @@ -22,13 +22,13 @@ *******************************************************************************/ #define CGOGN_CORE_DLL_EXPORT -#define CORE_UTILS_LOG_ENTRY_CPP_ +#define CGOGN_CORE_UTILS_LOG_ENTRY_CPP_ #include #include -#include -#include +#include +#include #include diff --git a/cgogn/core/utils/log_entry.h b/cgogn/core/utils/log_entry.h index 91638791..4ad01dfd 100644 --- a/cgogn/core/utils/log_entry.h +++ b/cgogn/core/utils/log_entry.h @@ -21,15 +21,15 @@ * * *******************************************************************************/ -#ifndef CORE_UTILS_LOG_ENTRY_H_ -#define CORE_UTILS_LOG_ENTRY_H_ +#ifndef CGOGN_CORE_UTILS_LOG_ENTRY_H_ +#define CGOGN_CORE_UTILS_LOG_ENTRY_H_ #include #include #include -#include -#include +#include +#include namespace cgogn { @@ -133,4 +133,4 @@ class CGOGN_CORE_API LogEntry final } // namespace logger } // namespace cgogn -#endif // CORE_UTILS_LOG_ENTRY_H_ +#endif // CGOGN_CORE_UTILS_LOG_ENTRY_H_ diff --git a/cgogn/core/utils/log_stream.cpp b/cgogn/core/utils/log_stream.cpp index afb7aec7..5e43aaee 100644 --- a/cgogn/core/utils/log_stream.cpp +++ b/cgogn/core/utils/log_stream.cpp @@ -22,13 +22,13 @@ *******************************************************************************/ #define CGOGN_CORE_DLL_EXPORT -#define CORE_UTILS_LOG_STREAM_CPP_ +#define CGOGN_CORE_UTILS_LOG_STREAM_CPP_ #include #include -#include -#include +#include +#include namespace cgogn { diff --git a/cgogn/core/utils/log_stream.h b/cgogn/core/utils/log_stream.h index 93bf0a79..f6447ce5 100644 --- a/cgogn/core/utils/log_stream.h +++ b/cgogn/core/utils/log_stream.h @@ -21,13 +21,13 @@ * * *******************************************************************************/ -#ifndef CORE_UTILS_LOG_STREAM_H_ -#define CORE_UTILS_LOG_STREAM_H_ +#ifndef CGOGN_CORE_UTILS_LOG_STREAM_H_ +#define CGOGN_CORE_UTILS_LOG_STREAM_H_ #include #include -#include +#include namespace cgogn { @@ -60,4 +60,4 @@ class CGOGN_CORE_API LogStream final } // namespace logger } // namespace cgogn -#endif // CORE_UTILS_LOG_STREAM_H_ +#endif // CGOGN_CORE_UTILS_LOG_STREAM_H_ diff --git a/cgogn/core/utils/logger.cpp b/cgogn/core/utils/logger.cpp index 3eee8ebc..fca1f7a1 100644 --- a/cgogn/core/utils/logger.cpp +++ b/cgogn/core/utils/logger.cpp @@ -22,10 +22,10 @@ *******************************************************************************/ #define CGOGN_CORE_DLL_EXPORT -#define CORE_UTILS_LOGGER_CPP_ +#define CGOGN_CORE_UTILS_LOGGER_CPP_ #include -#include +#include namespace cgogn { @@ -100,7 +100,7 @@ void Logger::add_file_output(const std::string& filename) if (fileout->get_filename() == filename) already_added = true; if (!already_added) - file_out_.push_back(make_unique(filename)); + file_out_.push_back(cgogn::make_unique(filename)); else std::cerr << "Logger::add_file_output: The file \"" << filename << "\" is already used by the logger." << std::endl; } diff --git a/cgogn/core/utils/logger.h b/cgogn/core/utils/logger.h index 57ce71fb..83f07e0f 100644 --- a/cgogn/core/utils/logger.h +++ b/cgogn/core/utils/logger.h @@ -21,17 +21,17 @@ * * *******************************************************************************/ -#ifndef CORE_UTILS_LOGGER_H_ -#define CORE_UTILS_LOGGER_H_ +#ifndef CGOGN_CORE_UTILS_LOGGER_H_ +#define CGOGN_CORE_UTILS_LOGGER_H_ #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include #define CGOGN_FILE_INFO ::cgogn::logger::internal::FileInfo(__FILE__, __LINE__) #define cgogn_log_info(emitter) ::cgogn::logger::Logger::get_logger().info(emitter,CGOGN_FILE_INFO) @@ -80,4 +80,4 @@ class CGOGN_CORE_API Logger final } // namespace logger } // namespace cgogn -#endif // CORE_UTILS_LOGGER_H_ +#endif // CGOGN_CORE_UTILS_LOGGER_H_ diff --git a/cgogn/core/utils/logger_output.cpp b/cgogn/core/utils/logger_output.cpp index 5d8e8f21..2344a3d2 100644 --- a/cgogn/core/utils/logger_output.cpp +++ b/cgogn/core/utils/logger_output.cpp @@ -22,12 +22,12 @@ *******************************************************************************/ #define CGOGN_CORE_DLL_EXPORT -#define CORE_UTILS_LOGGER_OUTPUT_CPP_ +#define CGOGN_CORE_UTILS_LOGGER_OUTPUT_CPP_ #include #include -#include +#include #include diff --git a/cgogn/core/utils/logger_output.h b/cgogn/core/utils/logger_output.h index d7c4f6b4..5f451f5e 100644 --- a/cgogn/core/utils/logger_output.h +++ b/cgogn/core/utils/logger_output.h @@ -21,13 +21,13 @@ * * *******************************************************************************/ -#ifndef CORE_UTILS_LOGGER_OUTPUT_H_ -#define CORE_UTILS_LOGGER_OUTPUT_H_ +#ifndef CGOGN_CORE_UTILS_LOGGER_OUTPUT_H_ +#define CGOGN_CORE_UTILS_LOGGER_OUTPUT_H_ #include #include -#include +#include namespace cgogn { @@ -95,4 +95,4 @@ class CGOGN_CORE_API FileOutput final : public LoggerOutput } // namespace logger } // namespace cgogn -#endif // CORE_UTILS_LOGGER_OUTPUT_H_ +#endif // CGOGN_CORE_UTILS_LOGGER_OUTPUT_H_ diff --git a/cgogn/core/utils/masks.h b/cgogn/core/utils/masks.h index da364b7c..29801c93 100644 --- a/cgogn/core/utils/masks.h +++ b/cgogn/core/utils/masks.h @@ -21,120 +21,184 @@ * * *******************************************************************************/ -#ifndef CORE_UTILS_MASKS_H_ -#define CORE_UTILS_MASKS_H_ +#ifndef CGOGN_CORE_UTILS_MASKS_H_ +#define CGOGN_CORE_UTILS_MASKS_H_ -#include #include +#include + +#include +#include namespace cgogn { -template -class MaskCell +/** + * @brief The CellFilters class + * Classes inheriting from CellFilters can be used as a parameter to map.foreach_cell() + * They can personalize the filtering function used to filter each Orbit traversal + */ +class CellFilters { public: - CGOGN_NOT_COPYABLE_NOR_MOVABLE(MaskCell); - inline MaskCell() {} - virtual ~MaskCell() {} - virtual void operator() (CellType) const final {} + CGOGN_NOT_COPYABLE_NOR_MOVABLE(CellFilters); + CellFilters() {} + virtual ~CellFilters() {} + virtual void operator() (uint32) const final {} - virtual CellType begin() const = 0; - virtual CellType next() const = 0; - virtual bool end() const = 0; + template + bool filter(CellType c) const { return true; } }; -template -class CellCache : public MaskCell +/** + * @brief The CellTraversor class + * Classes inheriting from CellTraversor can be used as a parameter to map.foreach_cell() + * They should have a nested class const_iterator (which has to be copy constructible, copy assignable, equality comparable, dereferenceable and incrementable (i.e. the expression ++it is defined)) + * They should provide the following methods : + * - template const_iterator begin() const + *" - template const_iterator end() const + */ +class CellTraversor { - MAP& map_; - mutable typename std::vector::const_iterator current_; - std::vector cells_; +public: + + CGOGN_NOT_COPYABLE_NOR_MOVABLE(CellTraversor); + inline CellTraversor() {} + virtual ~CellTraversor() {} + virtual void operator() (uint32) const final {} +}; + + +template +class CellCache : public CellTraversor +{ +public: + using iterator = std::vector::iterator; + using const_iterator = std::vector::const_iterator; public: CGOGN_NOT_COPYABLE_NOR_MOVABLE(CellCache); - CellCache(MAP& m) : map_(m) + inline CellCache(const MAP& m) : map_(m) + {} + + template + inline const_iterator begin() const { - cells_.reserve(4096u); - update(); + return cells_[CellType::ORBIT].begin(); } - CellType begin() const + template + inline iterator begin() { - current_ = cells_.begin(); - if (end()) return CellType(); - return *current_; + return cells_[CellType::ORBIT].begin(); } - CellType next() const + template + inline const_iterator end() const { - ++current_; - return *current_; + return cells_[CellType::ORBIT].end(); } - bool end() const { return current_ == cells_.end(); } + template + inline iterator end() + { + return cells_[CellType::ORBIT].end(); + } - void update() + template + inline std::size_t size() const { - cells_.clear(); - map_.foreach_cell([&] (CellType c) { cells_.push_back(c); }); - current_ = cells_.begin(); + return cells_[CellType::ORBIT].size(); } + + template + inline void build() + { + this->build([] (CellType) { return true; }); + } + + template + inline void build(const FilterFunction& filter) + { + static const Orbit ORBIT = CellType::ORBIT; + cells_[ORBIT].clear(); + cells_[ORBIT].reserve(4096u); + map_.foreach_cell([&] (CellType c) { cells_[ORBIT].push_back(c.dart); }, filter); + } + +private: + const MAP& map_; + std::array, NB_ORBITS> cells_; }; template -class BoundaryCache : public MaskCell +class BoundaryCache : public CellTraversor { - using CellType = typename MAP::Boundary; - - MAP& map_; - mutable typename std::vector::const_iterator current_; - std::vector cells_; - public: + using BoundaryCellType = typename MAP::Boundary; + using iterator = typename std::vector::iterator; + using const_iterator = typename std::vector::const_iterator; CGOGN_NOT_COPYABLE_NOR_MOVABLE(BoundaryCache); - BoundaryCache(MAP& m) : map_(m) + inline BoundaryCache(const MAP& m) : map_(m) { cells_.reserve(4096u); update(); } - CellType begin() const + template + inline const_iterator begin() const { - current_ = cells_.begin(); - if (end()) return CellType(); - return *current_; + static_assert(std::is_same::value, "BoundaryCache can only be used with BoundaryCellType"); + return cells_.begin(); } - CellType next() const + template + inline iterator begin() { - ++current_; - return *current_; + static_assert(std::is_same::value, "BoundaryCache can only be used with BoundaryCellType"); + return cells_.begin(); } - bool end() const { return current_ == cells_.end(); } + template + inline const_iterator end() const + { + static_assert(std::is_same::value, "BoundaryCache can only be used with BoundaryCellType"); + return cells_.end(); + } - void update() + template + inline iterator end() { + static_assert(std::is_same::value, "BoundaryCache can only be used with BoundaryCellType"); + return cells_.end(); + } + + template + inline void update() + { + static_assert(std::is_same::value, "BoundaryCache can only be used with BoundaryCellType"); cells_.clear(); typename MAP::DartMarker dm(map_); map_.foreach_dart([&] (Dart d) { if (!dm.is_marked(d)) { - CellType c(d); + BoundaryCellType c(d); dm.mark_orbit(c); if (map_.is_boundary(d)) cells_.push_back(c); } }); - current_ = cells_.begin(); } + +private: + const MAP& map_; + std::vector cells_; }; } // namespace cgogn -#endif // CORE_UTILS_MASKS_H_ +#endif // CGOGN_CORE_UTILS_MASKS_H_ diff --git a/cgogn/core/utils/name_types.cpp b/cgogn/core/utils/name_types.cpp index f0e50aed..97e925bb 100644 --- a/cgogn/core/utils/name_types.cpp +++ b/cgogn/core/utils/name_types.cpp @@ -23,8 +23,8 @@ #define CGOGN_CORE_DLL_EXPORT -#include -#include +#include +#include #ifdef __GNUG__ #include @@ -58,6 +58,11 @@ CGOGN_CORE_API std::string demangle(const std::string& str) #endif // __GNUG__ } +CGOGN_CORE_API std::string name_of_type_impl(const bool&) +{ + return "bool"; +} + CGOGN_CORE_API std::string name_of_type_impl(const int8&) { return "int8"; @@ -98,5 +103,16 @@ CGOGN_CORE_API std::string name_of_type_impl(const uint64&) return "uint64"; } +CGOGN_CORE_API std::string name_of_type_impl(const float32&) +{ + return "float32"; +} + +CGOGN_CORE_API std::string name_of_type_impl(const float64&) +{ + return "float64"; +} + } // namespace internal + } // namespace cgogn diff --git a/cgogn/core/utils/name_types.h b/cgogn/core/utils/name_types.h index 46fe967c..b2cfb995 100644 --- a/cgogn/core/utils/name_types.h +++ b/cgogn/core/utils/name_types.h @@ -21,8 +21,8 @@ * * *******************************************************************************/ -#ifndef CORE_UTILS_NAME_TYPES_H_ -#define CORE_UTILS_NAME_TYPES_H_ +#ifndef CGOGN_CORE_UTILS_NAME_TYPES_H_ +#define CGOGN_CORE_UTILS_NAME_TYPES_H_ #include #include @@ -41,9 +41,9 @@ #include #endif // __GNUG__ -#include -#include - +#include +#include +#include namespace cgogn { @@ -61,27 +61,18 @@ namespace internal CGOGN_CORE_API std::string demangle(const std::string& str); -template -struct sfinae_true : std::true_type{}; - -template -static auto test_name_of_type(int ) -> sfinae_true; -template -static auto test_name_of_type(long) -> std::false_type; -template -struct has_cgogn_name_of_type : decltype(test_name_of_type(0)){}; // implementation for classes which have a static cgogn_name_of_type() function (returning a std::string) template -inline auto name_of_type_impl(const T&) -> typename std::enable_if::value == false, std::string>::type; +inline auto name_of_type_impl(const T&) -> typename std::enable_if::value, std::string>::type; // implementation for other classes and type // declarations template -inline auto name_of_type_impl(const T&) -> typename std::enable_if::value == true, std::string>::type; +inline auto name_of_type_impl(const T&) -> typename std::enable_if::value, std::string>::type; template inline std::string name_of_type_impl(const std::list&); @@ -93,7 +84,9 @@ template inline std::string name_of_type_impl(const std::basic_string&); template -inline std::string name_of_type_impl(const std::array&); +inline std::string name_of_type_impl(const std::array&); + +CGOGN_CORE_API std::string name_of_type_impl(const bool&); CGOGN_CORE_API std::string name_of_type_impl(const int8&); @@ -111,6 +104,9 @@ CGOGN_CORE_API std::string name_of_type_impl(const int64&); CGOGN_CORE_API std::string name_of_type_impl(const uint64&); +CGOGN_CORE_API std::string name_of_type_impl(const float32&); + +CGOGN_CORE_API std::string name_of_type_impl(const float64&); // definitions @@ -127,17 +123,17 @@ inline std::string name_of_type_impl(const std::vector&) { return std::string("std::vector<") + name_of_type(T()) + std::string(">"); } template -inline std::string name_of_type_impl(const std::array&) +inline std::string name_of_type_impl(const std::array&) { return std::string("std::array<") + name_of_type(T()) + std::string(",") + std::to_string(N) + std::string(">"); } template -inline auto name_of_type_impl(const T&)->typename std::enable_if::value == true, std::string>::type +inline auto name_of_type_impl(const T&) -> typename std::enable_if::value, std::string>::type { return T::cgogn_name_of_type(); } template -inline auto name_of_type_impl(const T&)->typename std::enable_if::value == false, std::string>::type +inline auto name_of_type_impl(const T&) -> typename std::enable_if::value, std::string>::type { std::string type_name = demangle(std::string(typeid(T).name())); #ifdef __GNUG__ @@ -198,8 +194,6 @@ inline std::string name_of_type(const T& t) return internal::name_of_type_impl(t); } - - } // namespace cgogn -#endif // CORE_UTILS_NAME_TYPES_H_ +#endif // CGOGN_CORE_UTILS_NAME_TYPES_H_ diff --git a/cgogn/core/utils/numerics.h b/cgogn/core/utils/numerics.h new file mode 100644 index 00000000..ae7da6ff --- /dev/null +++ b/cgogn/core/utils/numerics.h @@ -0,0 +1,139 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef CGOGN_CORE_UTILS_NUMERICS_H_ +#define CGOGN_CORE_UTILS_NUMERICS_H_ + +#include +#include +#include +#include +#include + +#include + +namespace cgogn +{ + +namespace numerics +{ + +using int8 = std::int8_t; +using int16 = std::int16_t; +using int32 = std::int32_t; +using int64 = std::int64_t; + +using uint8 = std::uint8_t; +using uint16 = std::uint16_t; +using uint32 = std::uint32_t; +using uint64 = std::uint64_t; + +using float32 = float; +using float64 = double; + +template +inline auto almost_equal_relative(Scalar x, Scalar y, const Scalar max_rel_diff = std::numeric_limits::epsilon() ) -> typename std::enable_if::value, bool>::type +{ + const Scalar diff = std::fabs(x - y); + x = std::fabs(x); + y = std::fabs(y); + + return diff <= std::max(x, y) * max_rel_diff; +} + +template +inline auto almost_equal_absolute(Scalar x, Scalar y, const Scalar epsilon = std::numeric_limits::epsilon() ) -> typename std::enable_if::value, bool>::type +{ + cgogn_assert(epsilon > 0); + return std::fabs(y - x) < epsilon; +} + +template +inline Scalar scale_expand_within_0_1(Scalar x, const Integer n) +{ + static_assert(std::is_floating_point::value, "Floating point number required."); + static_assert(std::is_integral::value, "Integer number required."); + + for (Integer i = 1; i <= n; i++) + x = Real((Scalar(1) - std::cos(Scalar(M_PI) * x)) / Scalar(2)); + for (Integer i = -1; i >= n; i--) + x = Real(std::acos(Scalar(1) - Scalar(2) * x) / M_PI); + return x; +} + +template +inline Scalar scale_expand_towards_1(Scalar x, const Integer n) +{ + static_assert(std::is_floating_point::value, "Floating point number required."); + static_assert(std::is_integral::value, "Integer number required."); + + for (Integer i = 1; i <= n; i++) + x = Real(std::sin(x * Scalar(M_PI_2))); + for (Integer i = -1; i >= n; i--) + x = Real(std::asin(x) * Scalar(M_2_PI)); + return x; +} + +template +inline Scalar scale_to_0_1(const Scalar x, const Scalar min, const Scalar max) +{ + static_assert(std::is_floating_point::value, "Floating point number required."); + + return (x - min) / (max - min); +} + +template +inline Scalar scale_and_clamp_to_0_1(const Scalar x, const Scalar min, const Scalar max) +{ + static_assert(std::is_floating_point::value, "Floating point number required."); + + const Scalar v = (x - min) / (max - min); + return v < Scalar(0) ? Scalar(0) : (v > Scalar(1) ? Scalar(1) : v); +} + +template +inline void scale_centering_around_0(Scalar& min, Scalar& max) +{ + static_assert(std::is_floating_point::value, "Floating point number required."); + + min = std::min(min, -max); + max = std::max(max, -min); +} + +template +inline Scalar scale_to_0_1_around_one_half(const Scalar x, const Scalar min, const Scalar max) +{ + static_assert(std::is_floating_point::value, "Floating point number required."); + + const Scalar ma = std::max(max, -min); + const Scalar mi = std::min(min, -max); + return (x - mi) / (ma - mi); +} + +} // namespace numerics + +using namespace numerics; + +} // namespace cgogn + +#endif // CGOGN_CORE_UTILS_NUMERICS_H_ diff --git a/cgogn/core/utils/serialization.cpp b/cgogn/core/utils/serialization.cpp index b54f9fbe..c7961dce 100644 --- a/cgogn/core/utils/serialization.cpp +++ b/cgogn/core/utils/serialization.cpp @@ -22,7 +22,7 @@ *******************************************************************************/ #define CGOGN_CORE_DLL_EXPORT -#include +#include namespace cgogn { diff --git a/cgogn/core/utils/serialization.h b/cgogn/core/utils/serialization.h index 4d467cb3..570ed0e3 100644 --- a/cgogn/core/utils/serialization.h +++ b/cgogn/core/utils/serialization.h @@ -21,16 +21,18 @@ * * *******************************************************************************/ -#ifndef CORE_UTILS_SERIALIZATION_H_ -#define CORE_UTILS_SERIALIZATION_H_ +#ifndef CGOGN_CORE_UTILS_SERIALIZATION_H_ +#define CGOGN_CORE_UTILS_SERIALIZATION_H_ #include #include #include #include -#include -#include +#include +#include +#include +#include namespace cgogn { @@ -52,6 +54,49 @@ void save(std::ostream& ostream, T const* src, std::size_t quantity) ostream.write(reinterpret_cast(src), static_cast(quantity*sizeof(T))); } +template +inline typename std::enable_if::value, void>::type ostream_writer(std::ostream& o, bool binary, const T& x); +template +inline typename std::enable_if::value && !type_traits::is_iterable::value, void>::type ostream_writer(std::ostream& o, bool binary, const T& array); +template +inline typename std::enable_if::value && type_traits::is_iterable::value, void>::type ostream_writer(std::ostream& o, bool binary, const T& array); + +template +inline typename std::enable_if::value, void>::type ostream_writer(std::ostream& o, bool binary, const T& x) +{ + if (binary) + save(o,&x,1ul); + else + o << x; +} + +template +inline typename std::enable_if::value && !type_traits::is_iterable::value, void>::type ostream_writer(std::ostream& o, bool binary, const T& array) +{ + const std::size_t size = array.size(); + for(std::size_t i = 0ul ; i < size -1ul; ++i) + { + ostream_writer(o, binary, array[i]); + if (!binary) + o << " "; + } + ostream_writer(o, binary, array[size-1ul]); +} + +template +inline typename std::enable_if::value && type_traits::is_iterable::value, void>::type ostream_writer(std::ostream& o, bool binary, const T& array) +{ + const auto end = array.end(); + + for (auto it = array.begin(); it != end; ) + { + ostream_writer(o, binary, *it); + ++it; + if ((!binary) && it != end) + o << " "; + } +} + template std::size_t data_length(T const* /*src*/, std::size_t quantity) { @@ -263,4 +308,4 @@ std::size_t data_length(std::arrayconst* src, std::size_t quantity) } // namespace cgogn -#endif // CORE_UTILS_SERIALIZATION_H_ +#endif // CGOGN_CORE_UTILS_SERIALIZATION_H_ diff --git a/cgogn/core/utils/string.h b/cgogn/core/utils/string.h index b3c9126e..bbb27923 100644 --- a/cgogn/core/utils/string.h +++ b/cgogn/core/utils/string.h @@ -21,8 +21,8 @@ * * *******************************************************************************/ -#ifndef CORE_UTILS_STRING_H_ -#define CORE_UTILS_STRING_H_ +#ifndef CGOGN_CORE_UTILS_STRING_H_ +#define CGOGN_CORE_UTILS_STRING_H_ #include @@ -58,6 +58,32 @@ inline std::basic_string get_extension(const std::basic_string& return str.substr(dot + 1u); } +template +inline std::basic_string remove_extension(const std::basic_string& str) +{ + std::size_t dot = str.rfind('.'); + if (dot == std::basic_string::npos) + return str; + else + return str.substr(0,dot); +} + +template +inline bool equal_case_insensitive(const std::basic_string& str1, const std::basic_string& str2) +{ + if (str1.size() != str2.size()) + return false; + auto it1 = str1.begin(), it2 = str2.begin(), end = str1.end(); + for(auto end = str1.end(); it1 != end ;) + { + if (std::tolower(*it1) != std::tolower(*it2)) + return false; + ++it1; + ++it2; + } + return true; +} + } // namespace cgogn -#endif // CORE_UTILS_STRING_H_ +#endif // CGOGN_CORE_UTILS_STRING_H_ diff --git a/cgogn/core/utils/thread.cpp b/cgogn/core/utils/thread.cpp index bbe3bcbe..6899a80e 100644 --- a/cgogn/core/utils/thread.cpp +++ b/cgogn/core/utils/thread.cpp @@ -23,9 +23,9 @@ #define CGOGN_CORE_DLL_EXPORT -#include -#include -#include +#include +#include +#include namespace cgogn { diff --git a/cgogn/core/utils/thread.h b/cgogn/core/utils/thread.h index 50f28a66..4953b1cf 100644 --- a/cgogn/core/utils/thread.h +++ b/cgogn/core/utils/thread.h @@ -21,16 +21,16 @@ * * *******************************************************************************/ -#ifndef CORE_UTILS_THREAD_H_ -#define CORE_UTILS_THREAD_H_ +#ifndef CGOGN_CORE_UTILS_THREAD_H_ +#define CGOGN_CORE_UTILS_THREAD_H_ +#include #include -#include -#include -#include +#include +#include -#include +#include namespace cgogn { @@ -75,52 +75,6 @@ CGOGN_CORE_API void thread_stop(); CGOGN_CORE_API Buffers* get_dart_buffers(); CGOGN_CORE_API Buffers* get_uint_buffers(); -template -class ThreadFunction -{ -private: - - FUNC f_; - std::vector& elements_; - Barrier& sync1_; - Barrier& sync2_; - bool& finished_; - uint32 thread_order_; - -public: - - ThreadFunction( - FUNC f, - std::vector& elements, - Barrier& sync1, - Barrier& sync2, - bool& finished, - uint32 thread_order - ) : - f_(f), - elements_(elements), - sync1_(sync1), - sync2_(sync2), - finished_(finished), - thread_order_(thread_order) - {} - - void operator()() - { - thread_start(); - while (true) - { - sync2_.wait(); // wait for vectors to be filled - if (finished_) - break; - for (ELEM& e : elements_) - f_(e, thread_order_); - sync1_.wait(); // wait every thread has finished - } - thread_stop(); - } -}; - } // namespace cgogn -#endif // CORE_UTILS_THREAD_H_ +#endif // CGOGN_CORE_UTILS_THREAD_H_ diff --git a/cgogn/core/utils/thread_pool.cpp b/cgogn/core/utils/thread_pool.cpp index a9088f68..f3db8cc3 100644 --- a/cgogn/core/utils/thread_pool.cpp +++ b/cgogn/core/utils/thread_pool.cpp @@ -23,7 +23,7 @@ #define CGOGN_CORE_DLL_EXPORT -#include +#include namespace cgogn @@ -44,7 +44,9 @@ ThreadPool::~ThreadPool() std::unique_lock lock(queue_mutex_); stop_ = true; } +#if !(defined(CGOGN_WIN_VER) && (CGOGN_WIN_VER <= 61)) condition_.notify_all(); +#endif for(std::thread &worker: workers_) worker.join(); } diff --git a/cgogn/core/utils/thread_pool.h b/cgogn/core/utils/thread_pool.h index 1c688ed8..f2b41a18 100644 --- a/cgogn/core/utils/thread_pool.h +++ b/cgogn/core/utils/thread_pool.h @@ -53,8 +53,8 @@ *distribution. * ****************************************************************************/ -#ifndef CORE_UTILS_THREADPOOL_H_ -#define CORE_UTILS_THREADPOOL_H_ +#ifndef CGOGN_CORE_UTILS_THREADPOOL_H_ +#define CGOGN_CORE_UTILS_THREADPOOL_H_ #include #include @@ -65,9 +65,9 @@ #include #include -#include -#include -#include +#include +#include +#include namespace cgogn { @@ -75,10 +75,7 @@ namespace cgogn class CGOGN_CORE_API ThreadPool { public: ThreadPool(); - ThreadPool(const ThreadPool&) = delete; - ThreadPool& operator=(const ThreadPool&) = delete; - ThreadPool(ThreadPool&&) = delete; - ThreadPool& operator=(ThreadPool&&) = delete; + CGOGN_NOT_COPYABLE_NOR_MOVABLE(ThreadPool); template auto enqueue(const F& f, Args&&... args) @@ -137,4 +134,4 @@ auto ThreadPool::enqueue(const F& f, Args&&... args) } // namespace cgogn -#endif // CORE_UTILS_THREADPOOL_H_ +#endif // CGOGN_CORE_UTILS_THREADPOOL_H_ diff --git a/cgogn/core/utils/type_traits.h b/cgogn/core/utils/type_traits.h new file mode 100644 index 00000000..57b0e8f5 --- /dev/null +++ b/cgogn/core/utils/type_traits.h @@ -0,0 +1,128 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef CGOGN_CORE_UTILS_TYPE_TRAITS_H_ +#define CGOGN_CORE_UTILS_TYPE_TRAITS_H_ + +#include +#include + +namespace cgogn +{ +namespace type_traits +{ + +namespace internal +{ +template +struct sfinae_true : std::true_type {}; + +template +static auto test_operator_brackets(int32 ) -> sfinae_true()[0ul])>; +template +static auto test_operator_brackets(int64) -> std::false_type; + +template +static auto test_size_method(int32 ) -> sfinae_true().size())>; +template +static auto test_size_method(int64) -> std::false_type; + +template +static auto test_begin_method(int32 ) -> sfinae_true().begin())>; +template +static auto test_begin_method(int64) -> std::false_type; + +template +static auto test_iterable(int32 ) -> sfinae_true().end() != std::declval().end())>; +template +static auto test_iterable(int64) -> std::false_type; + +template +static auto test_name_of_type(int32 ) -> sfinae_true; +template +static auto test_name_of_type(int64) -> std::false_type; + +} // namespace internal + +template +struct has_operator_brackets : decltype(internal::test_operator_brackets(0)){}; + +template +struct has_size_method : decltype(internal::test_size_method(0)){}; + +template +struct has_begin_method : decltype(internal::test_begin_method(0)){}; + +template +struct is_iterable : decltype(internal::test_iterable(0)){}; + +template +struct has_cgogn_name_of_type : decltype(internal::test_name_of_type(0)){}; + + +template +struct nested_type; + +template +struct nested_type::value>::type> +{ + using type = typename std::remove_cv< typename std::remove_reference::type>::type; +}; + +template +struct nested_type::value>::type> +{ + using type = typename nested_type()[0ul])>::type >::type>::type; +}; + + +template +inline typename std::enable_if::value, uint32>::type get_nb_components(const T& ); +template +inline typename std::enable_if::value && has_begin_method::value, uint32>::type get_nb_components(const T& val); +template +inline typename std::enable_if::value && !has_begin_method::value, uint32>::type get_nb_components(const T& val); + + +template +inline typename std::enable_if::value, uint32>::type get_nb_components(const T& ) +{ + return 1u; +} + +template +inline typename std::enable_if::value && has_begin_method::value, uint32>::type get_nb_components(const T& val) +{ + return val.size() * get_nb_components(*(val.begin())); +} + +template +inline typename std::enable_if::value && !has_begin_method::value, uint32>::type get_nb_components(const T& val) +{ + return val.size() * get_nb_components(val[0]); +} + +} // namespace type_traits +} // namespace cgogn + +#endif // CGOGN_CORE_UTILS_TYPE_TRAITS_H_ diff --git a/cgogn/core/utils/unique_ptr.h b/cgogn/core/utils/unique_ptr.h index a9af63ff..a3663007 100644 --- a/cgogn/core/utils/unique_ptr.h +++ b/cgogn/core/utils/unique_ptr.h @@ -21,8 +21,8 @@ * * *******************************************************************************/ -#ifndef CORE_UTILS_MAKE_UNIQUE_H -#define CORE_UTILS_MAKE_UNIQUE_H +#ifndef CGOGN_CORE_UTILS_MAKE_UNIQUE_H +#define CGOGN_CORE_UTILS_MAKE_UNIQUE_H #include #include @@ -93,4 +93,4 @@ inline std::unique_ptr dynamic_cast_unique_ptr(std::unique_ptr&& ptr) } // namespace cgogn -#endif // CORE_UTILS_MAKE_UNIQUE_H +#endif // CGOGN_CORE_UTILS_MAKE_UNIQUE_H diff --git a/cgogn/geometry/CMakeLists.txt b/cgogn/geometry/CMakeLists.txt index cb881079..bffd5f74 100644 --- a/cgogn/geometry/CMakeLists.txt +++ b/cgogn/geometry/CMakeLists.txt @@ -2,21 +2,29 @@ project(cgogn_geometry LANGUAGES CXX ) +find_package(cgogn_core REQUIRED) + set(HEADER_FILES dll.h - algos/bounding_box.h + algos/bounding_box.h + algos/feature.h algos/area.h algos/centroid.h algos/normal.h algos/ear_triangulation.h algos/picking.h + algos/filtering.h + algos/length.h + algos/angle.h + functions/basics.h functions/area.h functions/normal.h functions/orientation.h functions/inclusion.h functions/intersection.h functions/distance.h - types/bounding_box.h + types/aabb.h + types/obb.h types/eigen.h types/geometry_traits.h types/plane_3d.h @@ -24,9 +32,10 @@ set(HEADER_FILES ) set(SOURCE_FILES + types/aabb.cpp + types/obb.cpp types/plane_3d.cpp types/vec.cpp - types/bounding_box.cpp ) add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) @@ -39,23 +48,15 @@ target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC target_include_directories(${PROJECT_NAME} PUBLIC $ - $ + $ ) -target_link_libraries(${PROJECT_NAME} cgogn_core) +target_link_libraries(${PROJECT_NAME} ${cgogn_core_LIBRARIES}) -install(DIRECTORY . - DESTINATION include/cgogn/geometry +install(FILES "dll.h" DESTINATION "include/cgogn/geometry") +install(DIRECTORY algos functions types + DESTINATION "include/cgogn/geometry" FILES_MATCHING PATTERN "*.h" ) -install(TARGETS ${PROJECT_NAME} - EXPORT ${PROJECT_NAME}Targets - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib -) - -if(CGOGN_BUILD_TESTS) - add_subdirectory(tests) -endif() +cgogn_create_package("${CGOGN_SOURCE_DIR};${CGOGN_THIRDPARTY_EIGEN3_INCLUDE_DIR}" "include") diff --git a/cgogn/geometry/algos/angle.h b/cgogn/geometry/algos/angle.h new file mode 100644 index 00000000..be0fe114 --- /dev/null +++ b/cgogn/geometry/algos/angle.h @@ -0,0 +1,76 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef CGOGN_GEOMETRY_ALGOS_ANGLE_H_ +#define CGOGN_GEOMETRY_ALGOS_ANGLE_H_ + +#include + +#include +#include + +namespace cgogn +{ + +namespace geometry +{ + +template +inline typename VEC3_T::Scalar angle_between_face_normals( + const MAP& map, + const typename MAP::Edge e, + const typename MAP::template VertexAttribute& position) +{ + using Scalar = typename VEC3_T::Scalar; + using Vertex = typename MAP::Vertex; + using Face = typename MAP::Face; + + if(map.is_incident_to_boundary(e)) + return Scalar(0) ; + + std::pair v = map.vertices(e); + const VEC3_T n1 = face_normal(map, Face(v.first.dart), position); + const VEC3_T n2 = face_normal(map, Face(v.second.dart), position); + + Scalar a = angle(n1, n2); + + return a ; +} + +template +inline void angle_between_face_normals( + const MAP& map, + const typename MAP::template VertexAttribute& position, + typename MAP::template Attribute& angles) +{ + map.foreach_cell([&] (Cell e) + { + angles[e] = angle_between_face_normals(map, e, position); + }); +} + +} // namespace geometry + +} // namespace cgogn + +#endif // CGOGN_GEOMETRY_ALGOS_ANGLE_H_ diff --git a/cgogn/geometry/algos/area.h b/cgogn/geometry/algos/area.h index 2978ee0a..fdfa04eb 100644 --- a/cgogn/geometry/algos/area.h +++ b/cgogn/geometry/algos/area.h @@ -21,11 +21,11 @@ * * *******************************************************************************/ -#ifndef GEOMETRY_ALGOS_AREA_H_ -#define GEOMETRY_ALGOS_AREA_H_ +#ifndef CGOGN_GEOMETRY_ALGOS_AREA_H_ +#define CGOGN_GEOMETRY_ALGOS_AREA_H_ -#include -#include +#include +#include namespace cgogn { @@ -34,18 +34,18 @@ namespace geometry { template -inline typename VEC3_T::Scalar triangle_area(const MAP& map, typename MAP::Face f, const typename MAP::template VertexAttributeHandler& position) +inline typename VEC3_T::Scalar triangle_area(const MAP& map, typename MAP::Face f, const typename MAP::template VertexAttribute& position) { using Vertex = typename MAP::Vertex; return triangle_area( - position[Vertex(f.dart)], - position[Vertex(map.phi1(f.dart))], - position[Vertex(map.phi_1(f.dart))] - ); + position[Vertex(f.dart)], + position[Vertex(map.phi1(f.dart))], + position[Vertex(map.phi_1(f.dart))] + ); } template -inline typename VEC3_T::Scalar convex_face_area(const MAP& map, typename MAP::Face f, const typename MAP::template VertexAttributeHandler& position) +inline typename VEC3_T::Scalar convex_face_area(const MAP& map, typename MAP::Face f, const typename MAP::template VertexAttribute& position) { using Vertex = typename MAP::Vertex; if (map.codegree(f) == 3) @@ -62,8 +62,41 @@ inline typename VEC3_T::Scalar convex_face_area(const MAP& map, typename MAP::Fa } } +template +inline typename VEC3_T::Scalar incident_faces_area( + const MAP& map, + const typename MAP::Edge e, + const typename MAP::template VertexAttribute& position) +{ + using Scalar = typename VEC3_T::Scalar; + using Face = typename MAP::Face; + + Scalar area(0) ; + + map.foreach_incident_face(e, [&] (Face f) + { + area += cgogn::geometry::convex_face_area(map, f, position);// / map.codegree(f) ; + }); + + return area ; +} + +template +inline void incident_faces_area( + const MAP& map, + const typename MAP::template VertexAttribute& position, + typename MAP::template EdgeAttribute& edge_area) +{ + using Edge = typename MAP::Edge; + + map.foreach_cell([&] (Edge e) + { + edge_area[e] = incident_faces_area(map, e, position); + }); +} + } // namespace geometry } // namespace cgogn -#endif // GEOMETRY_ALGOS_AREA_H_ +#endif // CGOGN_GEOMETRY_ALGOS_AREA_H_ diff --git a/cgogn/geometry/algos/bounding_box.h b/cgogn/geometry/algos/bounding_box.h index ae9405ec..f3bfdcdc 100644 --- a/cgogn/geometry/algos/bounding_box.h +++ b/cgogn/geometry/algos/bounding_box.h @@ -21,10 +21,11 @@ * * *******************************************************************************/ -#ifndef GEOMETRY_ALGO_BOUNDING_BOX_H_ -#define GEOMETRY_ALGO_BOUNDING_BOX_H_ +#ifndef CGOGN_GEOMETRY_ALGO_BOUNDING_BOX_H_ +#define CGOGN_GEOMETRY_ALGO_BOUNDING_BOX_H_ -#include +#include +#include namespace cgogn { @@ -33,15 +34,95 @@ namespace geometry { template -void compute_bounding_box(const ATTR& attr, BoundingBox& bb) +void compute_AABB(const ATTR& attr, AABB& bb) { bb.reset(); - for(const auto& p:attr) + for(const auto& p : attr) bb.add_point(p); } +template +void pca(const ATTR& attr) +{ + //mean centering data + +} + +template +void compute_OBB(const ATTR& attr, OBB& bb) +{ + bb.reset(); + + //compute the mean of the dataset (centroid) + Eigen::Vector3d mean; + mean.setZero(); + uint32 count = 0; + for(const auto& p : attr) + { + mean += Eigen::Vector3d(p[0], p[1], p[2]); + ++count; + } + mean /= count; + + //compute covariance matrix + Eigen::Matrix covariance; + covariance.setZero(); + + for(const auto& p : attr) + { + Eigen::Matrix point; + point[0] = p[0] - mean[0]; + point[1] = p[1] - mean[1]; + point[2] = p[2] - mean[2]; + + covariance(1, 1) += point[1] * point[1]; + covariance(1, 2) += point[1] * point[2]; + + covariance(2, 2) += point[2] * point[2]; + + point *= point[0]; + + covariance(0, 0) += point[0]; + covariance(0, 1) += point[1]; + covariance(0, 2) += point[2]; + } + + covariance (1, 0) = covariance (0, 1); + covariance (2, 0) = covariance (0, 2); + covariance (2, 1) = covariance (1, 2); + + covariance /= count; + + // Extract axes (i.e. eigenvectors) from covariance matrix. + Eigen::SelfAdjointEigenSolver eigen_solver(covariance, Eigen::ComputeEigenvectors); + Eigen::Matrix3d eivecs = eigen_solver.eigenvectors(); + + // Compute the size of the obb + Eigen::Vector3d ex; + Eigen::Vector3d t; + for(const auto& p : attr) + { + t = eivecs.transpose() * (p - mean); + + t(0) = std::abs(t(0)); t(1) = std::abs(t(1)); t(2) = std::abs(t(2)); + + if(t(0) > ex(0)) + ex(0) = t(0); + if(t(1) > ex(1)) + ex(1) = t(1); + if(t(2) > ex(2)) + ex(2) = t(2); + } + + bb.axis(eivecs); + bb.center(mean); + bb.extension(ex); +} + } // namespace geometry + } // namespace cgogn -#endif // GEOMETRY_ALGO_BOUNDING_BOX_H_ +#endif // CGOGN_GEOMETRY_ALGO_BOUNDING_BOX_H_ + diff --git a/cgogn/geometry/algos/centroid.h b/cgogn/geometry/algos/centroid.h index 6fcbabc2..d2cc3180 100644 --- a/cgogn/geometry/algos/centroid.h +++ b/cgogn/geometry/algos/centroid.h @@ -21,10 +21,11 @@ * * *******************************************************************************/ -#ifndef GEOMETRY_ALGOS_CENTROID_H_ -#define GEOMETRY_ALGOS_CENTROID_H_ +#ifndef CGOGN_GEOMETRY_ALGOS_CENTROID_H_ +#define CGOGN_GEOMETRY_ALGOS_CENTROID_H_ -#include +#include +#include namespace cgogn { @@ -33,10 +34,10 @@ namespace geometry { template -inline T centroid(const MAP& map, Cell c, const typename MAP::template VertexAttributeHandler& attribute) +inline T centroid(const MAP& map, Cell c, const typename MAP::template VertexAttribute& attribute) { T result; - result.setZero(); + set_zero(result); uint32 count = 0; map.foreach_incident_vertex(c, [&] (typename MAP::Vertex v) { @@ -51,4 +52,4 @@ inline T centroid(const MAP& map, Cell c, const typename MAP::template Ve } // namespace cgogn -#endif // GEOMETRY_ALGOS_CENTROID_H_ +#endif // CGOGN_GEOMETRY_ALGOS_CENTROID_H_ diff --git a/cgogn/geometry/algos/ear_triangulation.h b/cgogn/geometry/algos/ear_triangulation.h index 8e9556d5..abd3a9f0 100644 --- a/cgogn/geometry/algos/ear_triangulation.h +++ b/cgogn/geometry/algos/ear_triangulation.h @@ -21,13 +21,13 @@ * * *******************************************************************************/ -#ifndef GEOMETRY_ALGOS_EAR_TRIANGULATION_H_ -#define GEOMETRY_ALGOS_EAR_TRIANGULATION_H_ +#ifndef CGOGN_GEOMETRY_ALGOS_EAR_TRIANGULATION_H_ +#define CGOGN_GEOMETRY_ALGOS_EAR_TRIANGULATION_H_ #include -#include -#include +#include +#include namespace cgogn { @@ -35,11 +35,9 @@ namespace cgogn namespace geometry { - template class EarTriangulation { - using Vertex = typename MAP::Vertex; using Face = typename MAP::Face; using Scalar = typename VEC3::Scalar; @@ -63,7 +61,6 @@ class EarTriangulation prev_->next_ = this; } - static void close(VertexPoly* first, VertexPoly* last) { last->next_ = first; @@ -82,7 +79,6 @@ class EarTriangulation using VPMS = typename VertexPoly::VPMS; - /// normal to polygon (for orientation of angles) VEC3 normalPoly_; @@ -90,7 +86,7 @@ class EarTriangulation MAP& map_; /// ref on position attribute - const typename MAP::template VertexAttributeHandler& positions_; + const typename MAP::template VertexAttribute& positions_; /// map of ears VPMS ears_; @@ -104,16 +100,13 @@ class EarTriangulation /// initial face Face face_; - inline static bool cmp_VP(VertexPoly* lhs, VertexPoly* rhs) { - if (std::abs(lhs->value_ - rhs->value_)<0.2f) - return lhs->length_ < rhs->length_; + if (std::abs(lhs->value_ - rhs->value_) < 0.2f) + return lhs->length_ < rhs->length_; return lhs->value_ < rhs->value_; } - - void recompute_2_ears(VertexPoly* vp) { VertexPoly* vprev = vp->prev_; @@ -136,36 +129,35 @@ class EarTriangulation Scalar dotpr1 = std::acos(v1.dot(v2)) / Scalar(M_PI_2); Scalar dotpr2 = std::acos(-(v1.dot(v3))) / Scalar(M_PI_2); - if (!convex_) // if convex no need to test if vertex is an ear (yes) { VEC3 nv1 = v1.cross(v2); VEC3 nv2 = v1.cross(v3); if (nv1.dot(normalPoly_) < 0.0) - dotpr1 = 10.0f - dotpr1;// not an ears (concave) + dotpr1 = 10.0f - dotpr1;// not an ear (concave) if (nv2.dot(normalPoly_) < 0.0) - dotpr2 = 10.0f - dotpr2;// not an ears (concave) + dotpr2 = 10.0f - dotpr2;// not an ear (concave) - bool finished = (dotpr1>=5.0f) && (dotpr2>=5.0f); - for (typename VPMS::reverse_iterator it = ears_.rbegin(); (!finished)&&(it != ears_.rend())&&((*it)->value_ > 5.0f); ++it) + bool finished = (dotpr1 >= 5.0f) && (dotpr2 >= 5.0f); + for (auto it = ears_.rbegin(); (!finished) && (it != ears_.rend()) && ((*it)->value_ > 5.0f); ++it) { Vertex id = (*it)->vert_; const VEC3& P = positions_[id]; if ((dotpr1 < 5.0f) && (id.dart != vprev->vert_.dart)) - if (in_triangle(P, normalPoly_,Tb,Tc,Ta)) - dotpr1 = 5.0f;// not an ears ! + if (in_triangle(P, normalPoly_, Tb, Tc, Ta)) + dotpr1 = 5.0f; // not an ear ! if ((dotpr2 < 5.0f) && (id.dart != vnext->vert_.dart) ) if (in_triangle(P, normalPoly_,Td,Ta,Tb)) - dotpr2 = 5.0f;// not an ears ! + dotpr2 = 5.0f; // not an ear ! - finished = ((dotpr1 >= 5.0f)&&(dotpr2 >= 5.0f)); + finished = (dotpr1 >= 5.0f) && (dotpr2 >= 5.0f); } } - vp->value_ = dotpr1; + vp->value_ = dotpr1; vp->length_ = Scalar((Tb-Tc).squaredNorm()); vp->ear_ = ears_.insert(vp); vp2->value_ = dotpr2; @@ -176,10 +168,10 @@ class EarTriangulation convex_ = (*(ears_.rbegin()))->value_ < 5.0f; } - Scalar compute_ear_angle(const VEC3& P1, const VEC3& P2, const VEC3& P3) + Scalar compute_ear_angle(const VEC3& P1, const VEC3& P2, const VEC3& P3) { - VEC3 v1 = P1-P2; - VEC3 v2 = P3-P2; + VEC3 v1 = P1 - P2; + VEC3 v2 = P3 - P2; v1.normalize(); v2.normalize(); @@ -187,12 +179,11 @@ class EarTriangulation VEC3 vn = v1.cross(v2); if (vn.dot(normalPoly_) > 0.0f) - dotpr = 10.0f - dotpr; // not an ears (concave, store at the end for optimized use for intersections) + dotpr = 10.0f - dotpr; // not an ear (concave, store at the end for optimized use for intersections) return dotpr; } - bool compute_ear_intersection(VertexPoly* vp) { VertexPoly* endV = vp->prev_; @@ -204,9 +195,9 @@ class EarTriangulation while (curr != endV) { - if (in_triangle(positions_[curr->vert_], normalPoly_,Tb,Tc,Ta)) + if (in_triangle(positions_[curr->vert_], normalPoly_, Tb, Tc, Ta)) { - vp->value_ = 5.0f;// not an ears ! + vp->value_ = 5.0f; // not an ear ! return false; } curr = curr->next_; @@ -214,7 +205,6 @@ class EarTriangulation return true; } - public: /** @@ -223,7 +213,7 @@ class EarTriangulation * @param f the face to tringulate * @param position attribute of position to use */ - EarTriangulation(MAP& map, typename MAP::Face f, const typename MAP::template VertexAttributeHandler& position): + EarTriangulation(MAP& map, typename MAP::Face f, const typename MAP::template VertexAttribute& position) : map_(map), positions_(position), ears_(cmp_VP) @@ -236,7 +226,7 @@ class EarTriangulation } // compute normals for orientation - normalPoly_ = geometry::face_normal(map_,Cell(f.dart),position); + normalPoly_ = geometry::face_normal(map_, Cell(f.dart), position); // first pass create polygon in chained list with angle computation VertexPoly* vpp = nullptr; @@ -298,9 +288,9 @@ class EarTriangulation * @brief compute table of vertices indices (embeddings) of triangulation * @param table_indices */ - void compute_indices(std::vector& table_indices) + void compute_indices(std::vector& table_indices) { - table_indices.reserve((nb_verts_-2)*3); + table_indices.reserve((nb_verts_ - 2) * 3); if (nb_verts_ ==3) { @@ -320,18 +310,18 @@ class EarTriangulation table_indices.push_back(map_.get_embedding(be->vert_)); table_indices.push_back(map_.get_embedding(be->next_->vert_)); table_indices.push_back(map_.get_embedding(be->prev_->vert_)); - nb_verts_--; + --nb_verts_; if (nb_verts_ > 3) // do not recompute if only one triangle left { - //remove ears and two sided ears - ears_.erase(be_it); // from map of ears + // remove ears and two sided ears + ears_.erase(be_it); // from map of ears ears_.erase(be->next_->ear_); ears_.erase(be->prev_->ear_); be = VertexPoly::erase(be); // and remove ear vertex from polygon recompute_2_ears(be); } - else // finish (no need to update ears) + else // finish (no need to update ears) { // remove ear from polygon be = VertexPoly::erase(be); @@ -350,7 +340,7 @@ class EarTriangulation /** * @brief triangulate the face */ - void triangulate() + void triangulate() { while (nb_verts_ > 3) { @@ -359,12 +349,12 @@ class EarTriangulation VertexPoly* be = *be_it; map_.cut_face(be->prev_->vert_, be->next_->vert_); - nb_verts_--; + --nb_verts_; if (nb_verts_ > 3) // do not recompute if only one triangle left { - //remove ears and two sided ears - ears_.erase(be_it); // from map of ears + // remove ears and two sided ears + ears_.erase(be_it); // from map of ears ears_.erase(be->next_->ear_); ears_.erase(be->prev_->ear_); // replace dart to be in remaining poly @@ -372,7 +362,7 @@ class EarTriangulation be = VertexPoly::erase(be); // and remove ear vertex from polygon recompute_2_ears(be); } - else // finish (no need to update ears) + else // finish (no need to update ears) { // release memory of last triangle in polygon delete be->next_; @@ -393,9 +383,9 @@ class EarTriangulation * @param table_indices table of indices (vertex embedding) to fill (append) */ template -static void compute_ear_triangulation(MAP& map, typename MAP::Face f, const typename MAP::template VertexAttributeHandler& position, std::vector& table_indices) +static void compute_ear_triangulation(MAP& map, typename MAP::Face f, const typename MAP::template VertexAttribute& position, std::vector& table_indices) { - EarTriangulation tri(map, f, position); + EarTriangulation tri(map, f, position); tri.compute_indices(table_indices); } @@ -406,36 +396,33 @@ static void compute_ear_triangulation(MAP& map, typename MAP::Face f, const type * @param position */ template -static void apply_ear_triangulation(MAP& map,typename MAP::Face f, const typename MAP::template VertexAttributeHandler& position) +static void apply_ear_triangulation(MAP& map, typename MAP::Face f, const typename MAP::template VertexAttribute& position) { - EarTriangulation tri(map, f, position); + EarTriangulation tri(map, f, position); tri.triangulate(); } /** - * @brief apply ear triangulation to a face (face is cut + * @brief apply ear triangulation to a face (face is cut) * @param map * @param f * @param position */ template -static void apply_ear_triangulations(MAP& map, const typename MAP::template VertexAttributeHandler& position) +static void apply_ear_triangulations(MAP& map, const typename MAP::template VertexAttribute& position) { - map.template foreach_cell([&] (typename MAP::Face f) + map.template foreach_cell([&] (typename MAP::Face f) { - if (!map.has_degree(f,3)) + if (!map.has_codegree(f, 3)) { EarTriangulation tri(map, f, position); tri.triangulate(); } }); - } - - } // namespace geometry } // namespace cgogn -#endif // GEOMETRY_ALGOS_EAR_TRIANGULATION_H_ +#endif // CGOGN_GEOMETRY_ALGOS_EAR_TRIANGULATION_H_ diff --git a/cgogn/core/utils/precision.h b/cgogn/geometry/algos/feature.h similarity index 68% rename from cgogn/core/utils/precision.h rename to cgogn/geometry/algos/feature.h index 141f3ad5..660ab670 100644 --- a/cgogn/core/utils/precision.h +++ b/cgogn/geometry/algos/feature.h @@ -21,36 +21,34 @@ * * *******************************************************************************/ -#ifndef CORE_UTILS_PRECISION_H_ -#define CORE_UTILS_PRECISION_H_ +#ifndef CGOGN_GEOMETRY_ALGOS_FEATURE_H_ +#define CGOGN_GEOMETRY_ALGOS_FEATURE_H_ -#include -#include -#include -#include - -#include +#include namespace cgogn { -template -inline auto almost_equal_relative(Scalar x, Scalar y, const Scalar max_rel_diff = std::numeric_limits::epsilon() ) -> typename std::enable_if::value, bool>::type +namespace geometry { - const Scalar diff = std::fabs(x - y); - x = std::fabs(x); - y = std::fabs(y); - - return diff <= std::max(x, y) * max_rel_diff; -} -template -inline auto almost_equal_absolute(Scalar x, Scalar y, const Scalar epsilon = std::numeric_limits::epsilon() ) -> typename std::enable_if::value, bool>::type +template +void mark_feature_edges( + const MAP& map, + const typename MAP::template FaceAttribute& normal, + typename MAP::template CellMarker& feature_edge) { - cgogn_assert(epsilon > 0); - return std::fabs(y - x) < epsilon; + feature_edge.unmark_all(); + + map.foreach_cell([&] (typename MAP::Edge e) + { + if (angle(normal[e.dart], normal[map.phi2(e.dart)] > M_PI / 6.)) + feature_edge.mark(e); + }); } +} // namespace geometry + } // namespace cgogn -#endif // CORE_UTILS_PRECISION_H_ +#endif // CGOGN_GEOMETRY_ALGOS_FEATURE_H_ diff --git a/cgogn/geometry/algos/filtering.h b/cgogn/geometry/algos/filtering.h new file mode 100644 index 00000000..a474e5c0 --- /dev/null +++ b/cgogn/geometry/algos/filtering.h @@ -0,0 +1,188 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef CGOGN_GEOMETRY_ALGOS_FILTERING_H_ +#define CGOGN_GEOMETRY_ALGOS_FILTERING_H_ + +#include +#include + +namespace cgogn +{ + +namespace geometry +{ + +template +void filter_average( + const MAP& map, + const MASK& mask, + const typename MAP::template VertexAttribute& attribute_in, + typename MAP::template VertexAttribute& attribute_out) +{ + using Vertex = typename MAP::Vertex; + + map.parallel_foreach_cell([&] (Vertex v, uint32) + { + T sum; + set_zero(sum); + uint32 count = 0; + map.foreach_adjacent_vertex_through_edge(v, [&] (Vertex av) + { + sum += attribute_in[av]; + ++count; + }); + attribute_out[v] = sum / typename vector_traits::Scalar(count); + }, + mask); +} + +template +void filter_average( + const MAP& map, + const typename MAP::template VertexAttribute& attribute_in, + typename MAP::template VertexAttribute& attribute_out) +{ + filter_average(map, CellFilters(), attribute_in, attribute_out); +} + +template +void filter_bilateral( + const MAP& map, + const MASK& mask, + const typename MAP::template VertexAttribute& position_in, + typename MAP::template VertexAttribute& position_out, + const typename MAP::template VertexAttribute& normal) +{ + using Scalar = typename vector_traits::Scalar; + using Vertex = typename MAP::Vertex; + using Edge = typename MAP::Edge; + + Scalar length_sum = 0; + Scalar angle_sum = 0; + uint32 nb_edges = 0; + + map.foreach_cell([&] (Edge e) + { + std::pair v = map.vertices(e); + VEC3 edge = position_in[v.first] - position_in[v.second]; + length_sum += edge.norm(); + angle_sum += angle(normal[v.first], normal[v.second]); + ++nb_edges; + }, + mask); + + Scalar sigmaC = 1.0 * (length_sum / Scalar(nb_edges)); + Scalar sigmaS = 2.5 * (angle_sum / Scalar(nb_edges)); + + map.parallel_foreach_cell([&] (Vertex v, uint32) + { + const VEC3& n = normal[v]; + + Scalar sum = 0, normalizer = 0; + map.foreach_adjacent_vertex_through_edge(v, [&] (Vertex av) + { + VEC3 edge = position_in[av] - position_in[v]; + Scalar t = edge.norm(); + Scalar h = n.dot(edge); + Scalar wcs = std::exp((-1.0 * (t * t) / (2.0 * sigmaC * sigmaC)) + (-1.0 * (h * h) / (2.0 * sigmaS * sigmaS))); + sum += wcs * h; + normalizer += wcs; + }); + + position_out[v] = position_in[v] + ((sum / normalizer) * n); + }, + mask); +} + +template +void filter_bilateral( + const MAP& map, + const typename MAP::template VertexAttribute& position_in, + typename MAP::template VertexAttribute& position_out, + const typename MAP::template VertexAttribute& normal) +{ + filter_bilateral(map, CellFilters(), position_in, position_out, normal); +} + +template +void filter_taubin( + const MAP& map, + const MASK& mask, + typename MAP::template VertexAttribute& position, + typename MAP::template VertexAttribute& position_tmp) +{ + using Scalar = typename vector_traits::Scalar; + using Vertex = typename MAP::Vertex; + using Edge = typename MAP::Edge; + + const Scalar lambda = 0.6307; + const Scalar mu = 0.6732; + + map.parallel_foreach_cell([&] (Vertex v, uint32) + { + VEC3 avg; + set_zero(avg); + uint32 count = 0; + map.foreach_adjacent_vertex_through_edge(v, [&] (Vertex av) + { + avg += position[av]; + ++count; + }); + avg /= Scalar(count); + const VEC3& p = position[v]; + position_tmp[v] = p + ((avg - p) * lambda); + }, + mask); + + map.parallel_foreach_cell([&] (Vertex v, uint32) + { + VEC3 avg; + set_zero(avg); + uint32 count = 0; + map.foreach_adjacent_vertex_through_edge(v, [&] (Vertex av) + { + avg += position_tmp[av]; + ++count; + }); + avg /= Scalar(count); + const VEC3& p = position_tmp[v]; + position[v] = p + ((avg - p) * mu); + }, + mask); +} + +template +void filter_taubin( + const MAP& map, + typename MAP::template VertexAttribute& position, + typename MAP::template VertexAttribute& position_tmp) +{ + filter_taubin(map, CellFilters(), position, position_tmp); +} + +} // namespace geometry + +} // namespace cgogn + +#endif // CGOGN_GEOMETRY_ALGOS_FILTERING_H_ diff --git a/cgogn/geometry/algos/length.h b/cgogn/geometry/algos/length.h new file mode 100644 index 00000000..cb6d9ea4 --- /dev/null +++ b/cgogn/geometry/algos/length.h @@ -0,0 +1,83 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef CGOGN_GEOMETRY_ALGOS_LENGTH_H_ +#define CGOGN_GEOMETRY_ALGOS_LENGTH_H_ + +#include + +#include + +namespace cgogn +{ + +namespace geometry +{ + +template +inline VEC3_T vector_from( + const MAP& map, + const Dart d, + const typename MAP::template VertexAttribute& position) +{ + using Vertex = typename MAP::Vertex; + + VEC3_T vec = position[Vertex(map.phi1(d))] ; + vec -= position[Vertex(d)] ; + return vec ; +} + +template +inline typename VEC3_T::Scalar edge_length( + const MAP& map, + const typename MAP::Edge e, + const typename MAP::template VertexAttribute& position) +{ + return vector_from(map, e.dart, position).norm(); +} + +template +inline typename VEC3_T::Scalar mean_edge_length( + const MAP& map, + const typename MAP::template VertexAttribute& position) +{ + using Scalar = typename VEC3_T::Scalar; + using Edge = typename MAP::Edge; + + Scalar length(0); + uint32 nbe = 0; + + map.foreach_cell([&](Edge e) + { + length += edge_length(map, e, position); + ++nbe; + }); + + return length / Scalar(nbe); +} + +} // namespace geometry + +} // namespace cgogn + +#endif // CGOGN_GEOMETRY_ALGOS_LENGTH_H_ diff --git a/cgogn/geometry/algos/normal.h b/cgogn/geometry/algos/normal.h index 180e49dd..da41e5d7 100644 --- a/cgogn/geometry/algos/normal.h +++ b/cgogn/geometry/algos/normal.h @@ -21,16 +21,16 @@ * * *******************************************************************************/ -#ifndef GEOMETRY_ALGOS_NORMAL_H_ -#define GEOMETRY_ALGOS_NORMAL_H_ +#ifndef CGOGN_GEOMETRY_ALGOS_NORMAL_H_ +#define CGOGN_GEOMETRY_ALGOS_NORMAL_H_ -#include -#include +#include +#include -#include -#include -#include -#include +#include +#include +#include +#include namespace cgogn { @@ -39,7 +39,7 @@ namespace geometry { template -inline VEC3 triangle_normal(const MAP& map, Cell f, const typename MAP::template VertexAttributeHandler& position) +inline VEC3 triangle_normal(const MAP& map, Cell f, const typename MAP::template VertexAttribute& position) { using Vertex = typename MAP::Vertex; VEC3 n = triangle_normal( @@ -52,7 +52,7 @@ inline VEC3 triangle_normal(const MAP& map, Cell f, const typename } template -inline VEC3 newell_normal(const MAP& map, Cell f, const typename MAP::template VertexAttributeHandler& position) +inline VEC3 newell_normal(const MAP& map, Cell f, const typename MAP::template VertexAttribute& position) { using Vertex = typename MAP::Vertex; using Scalar = typename cgogn::geometry::vector_traits::Scalar; @@ -70,7 +70,7 @@ inline VEC3 newell_normal(const MAP& map, Cell f, const typename MA } template -inline VEC3 face_normal(const MAP& map, Cell f, const typename MAP::template VertexAttributeHandler& position) +inline VEC3 face_normal(const MAP& map, Cell f, const typename MAP::template VertexAttribute& position) { if (map.has_codegree(f, 3)) return triangle_normal(map, f, position); @@ -79,7 +79,7 @@ inline VEC3 face_normal(const MAP& map, Cell f, const typename MAP: } template -inline VEC3 vertex_normal(const MAP& map, Cell v, const typename MAP::template VertexAttributeHandler& position) +inline VEC3 vertex_normal(const MAP& map, Cell v, const typename MAP::template VertexAttribute& position) { using Vertex = typename MAP::Vertex; using Scalar = typename VEC3::Scalar; @@ -101,7 +101,7 @@ inline VEC3 vertex_normal(const MAP& map, Cell v, const typename M } template -inline VEC3 vertex_normal(const MAP& map, Cell v, const typename MAP::template VertexAttributeHandler& position, const typename MAP::template AttributeHandler& fnormal) +inline VEC3 vertex_normal(const MAP& map, Cell v, const typename MAP::template VertexAttribute& position, const typename MAP::template Attribute& fnormal) { using Vertex = typename MAP::Vertex; using Scalar = typename VEC3::Scalar; @@ -123,7 +123,7 @@ inline VEC3 vertex_normal(const MAP& map, Cell v, const typename M } template -inline void compute_normal_faces(MAP& map, const typename MAP::template VertexAttributeHandler& position, typename MAP::template AttributeHandler& normal) +inline void compute_normal_faces(const MAP& map, const typename MAP::template VertexAttribute& position, typename MAP::template Attribute& normal) { map.parallel_foreach_cell([&] (Cell f, uint32) { @@ -132,7 +132,7 @@ inline void compute_normal_faces(MAP& map, const typename MAP::template VertexAt } template -inline void compute_normal_vertices(MAP& map, const typename MAP::template VertexAttributeHandler& position, typename MAP::template AttributeHandler& normal) +inline void compute_normal_vertices(const MAP& map, const typename MAP::template VertexAttribute& position, typename MAP::template Attribute& normal) { map.parallel_foreach_cell([&] (Cell v, uint32) { @@ -141,7 +141,7 @@ inline void compute_normal_vertices(MAP& map, const typename MAP::template Verte } template -inline void compute_normal_vertices(MAP& map, const typename MAP::template VertexAttributeHandler& position, const typename MAP::template AttributeHandler& fnormal, typename MAP::template AttributeHandler& normal) +inline void compute_normal_vertices(const MAP& map, const typename MAP::template VertexAttribute& position, const typename MAP::template Attribute& fnormal, typename MAP::template Attribute& normal) { map.parallel_foreach_cell([&] (Cell v, uint32) { @@ -153,4 +153,4 @@ inline void compute_normal_vertices(MAP& map, const typename MAP::template Verte } // namespace cgogn -#endif // GEOMETRY_ALGOS_NORMAL_H_ +#endif // CGOGN_GEOMETRY_ALGOS_NORMAL_H_ diff --git a/cgogn/geometry/algos/picking.h b/cgogn/geometry/algos/picking.h index fbc5cc52..a08bfc32 100644 --- a/cgogn/geometry/algos/picking.h +++ b/cgogn/geometry/algos/picking.h @@ -21,18 +21,18 @@ * * *******************************************************************************/ -#ifndef GEOMETRY_ALGOS_PICKING_H_ -#define GEOMETRY_ALGOS_PICKING_H_ +#ifndef CGOGN_GEOMETRY_ALGOS_PICKING_H_ +#define CGOGN_GEOMETRY_ALGOS_PICKING_H_ -#include -#include -#include +#include +#include +#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include @@ -43,7 +43,7 @@ namespace geometry { template -inline void picking_internal_face(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector>& selected ) +inline void picking_internal_face(MAP& m, const typename MAP::template VertexAttribute& position, const VEC3& A, const VEC3& B, typename std::vector>& selected ) { using Vertex = typename MAP::Vertex; using Face = typename MAP::Face; @@ -106,7 +106,7 @@ inline void picking_internal_face(MAP& m, const typename MAP::template VertexAtt } template -bool picking_faces(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector& selected) +bool picking_faces(MAP& m, const typename MAP::template VertexAttribute& position, const VEC3& A, const VEC3& B, typename std::vector& selected) { typename std::vector> sel; picking_internal_face(m, position, A, B, sel); @@ -122,7 +122,7 @@ bool picking_faces(MAP& m, const typename MAP::template VertexAttributeHandler -bool picking_vertices(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector& selected) +bool picking_vertices(MAP& m, const typename MAP::template VertexAttribute& position, const VEC3& A, const VEC3& B, typename std::vector& selected) { using Vertex = typename MAP::Vertex; using Face = typename MAP::Face; @@ -162,7 +162,7 @@ bool picking_vertices(MAP& m, const typename MAP::template VertexAttributeHandle } template -bool picking_edges(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector& selected) +bool picking_edges(MAP& m, const typename MAP::template VertexAttribute& position, const VEC3& A, const VEC3& B, typename std::vector& selected) { using Vertex = typename MAP::Vertex; using Edge = typename MAP::Edge; @@ -204,7 +204,7 @@ bool picking_edges(MAP& m, const typename MAP::template VertexAttributeHandler -bool picking_volumes(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector& selected) +bool picking_volumes(MAP& m, const typename MAP::template VertexAttribute& position, const VEC3& A, const VEC3& B, typename std::vector& selected) { //here used Face2 for selecting the 2 volumes incident to selected faces @@ -236,4 +236,4 @@ bool picking_volumes(MAP& m, const typename MAP::template VertexAttributeHandler } // namespace cgogn -#endif // GEOMETRY_ALGOS_PICKING_H_ +#endif // CGOGN_GEOMETRY_ALGOS_PICKING_H_ diff --git a/cgogn/geometry/dll.h b/cgogn/geometry/dll.h index 602df936..5ba224ed 100644 --- a/cgogn/geometry/dll.h +++ b/cgogn/geometry/dll.h @@ -21,8 +21,8 @@ * * *******************************************************************************/ -#ifndef GEOMETRY_DLL_H_ -#define GEOMETRY_DLL_H_ +#ifndef CGOGN_GEOMETRY_DLL_H_ +#define CGOGN_GEOMETRY_DLL_H_ /** * \brief Linkage declaration for CGOGN symbols. @@ -37,4 +37,4 @@ #define CGOGN_GEOMETRY_API #endif -#endif // GEOMETRY_DLL_H_ +#endif // CGOGN_GEOMETRY_DLL_H_ diff --git a/cgogn/geometry/examples/CMakeLists.txt b/cgogn/geometry/examples/CMakeLists.txt new file mode 100644 index 00000000..04ac3acd --- /dev/null +++ b/cgogn/geometry/examples/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.0 FATAL_ERROR) + +project(cgogn_geometry_examples + LANGUAGES CXX +) + +find_package(cgogn_core REQUIRED) +find_package(cgogn_io REQUIRED) +find_package(cgogn_rendering REQUIRED) +find_package(QOGLViewer REQUIRED) + +set(CMAKE_AUTOMOC ON) + +set(CGOGN_TEST_PREFIX "test_") +set(CGOGN_TEST_MESHES_PATH "${CMAKE_SOURCE_DIR}/data/meshes/") +add_definitions("-DCGOGN_TEST_MESHES_PATH=${CGOGN_TEST_MESHES_PATH}") + + +add_executable(filtering filtering.cpp) +target_link_libraries(filtering ${cgogn_core_LIBRARIES} ${cgogn_io_LIBRARIES} ${cgogn_rendering_LIBRARIES} ${QOGLViewer_LIBRARIES}) diff --git a/cgogn/geometry/examples/filtering.cpp b/cgogn/geometry/examples/filtering.cpp new file mode 100644 index 00000000..c299d9bb --- /dev/null +++ b/cgogn/geometry/examples/filtering.cpp @@ -0,0 +1,445 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) + +using Map2 = cgogn::CMap2; +using Vertex = Map2::Vertex; +using Edge = Map2::Edge; + +using Vec3 = Eigen::Vector3d; +//using Vec3 = cgogn::geometry::Vec_T>; + +template +using VertexAttribute = Map2::VertexAttribute; + + +class CustomFilter : public cgogn::CellFilters +{ +public: + + CustomFilter(const VertexAttribute& p) : position_(p) {} + + bool filter(Vertex v) const + { + return position_[v][0] > 0; + } + +protected: + + const VertexAttribute& position_; +}; + + +class Viewer : public QOGLViewer +{ +public: + + Viewer(); + Viewer(const Viewer&) = delete; + Viewer& operator=(const Viewer&) = delete; + + virtual void draw(); + virtual void init(); + void update_bb(); + + virtual void keyPressEvent(QKeyEvent *); + void import(const std::string& surface_mesh); + virtual ~Viewer(); + virtual void closeEvent(QCloseEvent *e); + +private: + + Map2 map_; + + VertexAttribute vertex_position_; + VertexAttribute vertex_position2_; + VertexAttribute vertex_normal_; + + cgogn::CellCache cell_cache_; + std::unique_ptr filter_; + + cgogn::geometry::AABB bb_; + + std::unique_ptr render_; + + std::unique_ptr vbo_pos_; + std::unique_ptr vbo_norm_; + std::unique_ptr vbo_color_; + std::unique_ptr vbo_sphere_sz_; + + std::unique_ptr param_edge_; + std::unique_ptr param_flat_; + std::unique_ptr param_normal_; + std::unique_ptr param_phong_; + std::unique_ptr param_point_sprite_; + + std::unique_ptr drawer_; + std::unique_ptr drawer_rend_; + + bool phong_rendering_; + bool flat_rendering_; + bool vertices_rendering_; + bool edge_rendering_; + bool normal_rendering_; + bool bb_rendering_; +}; + + + +// +// IMPLEMENTATION +// + + +void Viewer::import(const std::string& surface_mesh) +{ + cgogn::io::import_surface(map_, surface_mesh); + + vertex_position_ = map_.get_attribute("position"); + if (!vertex_position_.is_valid()) + { + cgogn_log_error("Viewer::import") << "Missing attribute position. Aborting."; + std::exit(EXIT_FAILURE); + } + + vertex_position2_ = map_.add_attribute("position2"); + map_.copy_attribute(vertex_position2_, vertex_position_); + + vertex_normal_ = map_.add_attribute("normal"); + cgogn::geometry::compute_normal_vertices(map_, vertex_position_, vertex_normal_); + + cell_cache_.build(); + cell_cache_.build(); + + filter_ = cgogn::make_unique(vertex_position_); + + cgogn::geometry::compute_AABB(vertex_position_, bb_); + setSceneRadius(bb_.diag_size()/2.0); + Vec3 center = bb_.center(); + setSceneCenter(qoglviewer::Vec(center[0], center[1], center[2])); + showEntireScene(); +} + +Viewer::~Viewer() +{} + +void Viewer::closeEvent(QCloseEvent*) +{ + filter_.reset(); + render_.reset(); + drawer_rend_.reset(); + vbo_pos_.reset(); + vbo_norm_.reset(); + vbo_color_.reset(); + vbo_sphere_sz_.reset(); + drawer_.reset(); +} + +Viewer::Viewer() : + map_(), + vertex_position_(), + vertex_normal_(), + cell_cache_(map_), + bb_(), + render_(nullptr), + drawer_rend_(nullptr), + vbo_pos_(nullptr), + vbo_norm_(nullptr), + vbo_color_(nullptr), + vbo_sphere_sz_(nullptr), + drawer_(nullptr), + phong_rendering_(true), + flat_rendering_(false), + vertices_rendering_(false), + edge_rendering_(false), + normal_rendering_(false), + bb_rendering_(true) +{} + +void Viewer::keyPressEvent(QKeyEvent *ev) +{ + switch (ev->key()) { + case Qt::Key_P: + phong_rendering_ = true; + flat_rendering_ = false; + break; + case Qt::Key_F: + flat_rendering_ = true; + phong_rendering_ = false; + break; + case Qt::Key_N: + normal_rendering_ = !normal_rendering_; + break; + case Qt::Key_E: + edge_rendering_ = !edge_rendering_; + break; + case Qt::Key_V: + vertices_rendering_ = !vertices_rendering_; + break; +// case Qt::Key_B: +// bb_rendering_ = !bb_rendering_; +// break; + case Qt::Key_A: { + cgogn::geometry::filter_average(map_, *filter_, vertex_position_, vertex_position2_); +// cgogn::geometry::filter_average(map_, cell_cache_, vertex_position_, vertex_position2_); + map_.swap_attributes(vertex_position_, vertex_position2_); + cgogn::geometry::compute_normal_vertices(map_, vertex_position_, vertex_normal_); + cgogn::rendering::update_vbo(vertex_position_, vbo_pos_.get()); + cgogn::rendering::update_vbo(vertex_normal_, vbo_norm_.get()); + cgogn::rendering::update_vbo(vertex_normal_, vbo_color_.get(), [] (const Vec3& n) -> std::array + { + return {float(std::abs(n[0])), float(std::abs(n[1])), float(std::abs(n[2]))}; + }); + update_bb(); + setSceneRadius(bb_.diag_size()/2.0); + break; + } + case Qt::Key_B: + cgogn::geometry::filter_bilateral(map_, cell_cache_, vertex_position_, vertex_position2_, vertex_normal_); + map_.swap_attributes(vertex_position_, vertex_position2_); + cgogn::geometry::compute_normal_vertices(map_, vertex_position_, vertex_normal_); + cgogn::rendering::update_vbo(vertex_position_, vbo_pos_.get()); + cgogn::rendering::update_vbo(vertex_normal_, vbo_norm_.get()); + cgogn::rendering::update_vbo(vertex_normal_, vbo_color_.get(), [] (const Vec3& n) -> std::array + { + return {float(std::abs(n[0])), float(std::abs(n[1])), float(std::abs(n[2]))}; + }); + update_bb(); + setSceneRadius(bb_.diag_size()/2.0); + break; + case Qt::Key_T: + cgogn::geometry::filter_taubin(map_, cell_cache_, vertex_position_, vertex_position2_); + cgogn::geometry::compute_normal_vertices(map_, vertex_position_, vertex_normal_); + cgogn::rendering::update_vbo(vertex_position_, vbo_pos_.get()); + cgogn::rendering::update_vbo(vertex_normal_, vbo_norm_.get()); + cgogn::rendering::update_vbo(vertex_normal_, vbo_color_.get(), [] (const Vec3& n) -> std::array + { + return {float(std::abs(n[0])), float(std::abs(n[1])), float(std::abs(n[2]))}; + }); + update_bb(); + setSceneRadius(bb_.diag_size()/2.0); + break; + default: + break; + } + // enable QGLViewer keys + QOGLViewer::keyPressEvent(ev); + //update drawing + update(); +} + +void Viewer::draw() +{ + QMatrix4x4 proj; + QMatrix4x4 view; + camera()->getProjectionMatrix(proj); + camera()->getModelViewMatrix(view); + + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.0f, 2.0f); + if (flat_rendering_) + { + param_flat_->bind(proj, view); + render_->draw(cgogn::rendering::TRIANGLES); + param_flat_->release(); + } + + if (phong_rendering_) + { + param_phong_->bind(proj, view); + render_->draw(cgogn::rendering::TRIANGLES); + param_phong_->release(); + } + glDisable(GL_POLYGON_OFFSET_FILL); + + if (vertices_rendering_) + { + param_point_sprite_->bind(proj, view); + render_->draw(cgogn::rendering::POINTS); + param_point_sprite_->release(); + } + + if (edge_rendering_) + { + param_edge_->bind(proj, view); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + render_->draw(cgogn::rendering::LINES); + glDisable(GL_BLEND); + param_edge_->release(); + } + + if (normal_rendering_) + { + param_normal_->bind(proj, view); + render_->draw(cgogn::rendering::POINTS); + param_normal_->release(); + } + + if (bb_rendering_) + drawer_rend_->draw(proj, view, this); +} + +void Viewer::init() +{ + glClearColor(0.1f,0.1f,0.3f,0.0f); + + vbo_pos_ = cgogn::make_unique(); + cgogn::rendering::update_vbo(vertex_position_, vbo_pos_.get()); + + vbo_norm_ = cgogn::make_unique(); + cgogn::rendering::update_vbo(vertex_normal_, vbo_norm_.get()); + + // fill a color vbo with abs of normals + vbo_color_ = cgogn::make_unique(); + cgogn::rendering::update_vbo(vertex_normal_, vbo_color_.get(), [] (const Vec3& n) -> std::array + { + return {float(std::abs(n[0])), float(std::abs(n[1])), float(std::abs(n[2]))}; + }); + + // fill a sphere size vbo + vbo_sphere_sz_ = cgogn::make_unique(1); + cgogn::rendering::update_vbo(vertex_normal_, vbo_sphere_sz_.get(), [&] (const Vec3& n) -> float + { + return bb_.diag_size()/1000.0 * (1.0 + 2.0*std::abs(n[2])); + }); + + render_ = cgogn::make_unique(); + + render_->init_primitives(map_, cgogn::rendering::POINTS); + render_->init_primitives(map_, cgogn::rendering::LINES); + render_->init_primitives(map_, cgogn::rendering::TRIANGLES, &vertex_position_); + + param_point_sprite_ = cgogn::rendering::ShaderPointSpriteSize::generate_param(); + param_point_sprite_->set_all_vbos(vbo_pos_.get(), vbo_sphere_sz_.get()); + param_point_sprite_->color_ = QColor(255, 0, 0); + +// shader_edge_ = new cgogn::rendering::ShaderBoldLine() ; +// param_edge_ = shader_edge_->generate_param(); + param_edge_ = cgogn::rendering::ShaderBoldLine::generate_param(); + param_edge_->set_position_vbo(vbo_pos_.get()); + param_edge_->color_ = QColor(255,255,0); + param_edge_->width_= 2.5f; + + param_flat_ = cgogn::rendering::ShaderFlat::generate_param(); + param_flat_->set_position_vbo(vbo_pos_.get()); + param_flat_->front_color_ = QColor(0,200,0); + param_flat_->back_color_ = QColor(0,0,200); + param_flat_->ambiant_color_ = QColor(5,5,5); + + param_normal_ = cgogn::rendering::ShaderVectorPerVertex::generate_param(); + param_normal_->set_all_vbos(vbo_pos_.get(), vbo_norm_.get()); + param_normal_->color_ = QColor(200,0,200); + param_normal_->length_ = bb_.diag_size()/50; + + param_phong_ = cgogn::rendering::ShaderPhongColor::generate_param(); + param_phong_->set_all_vbos(vbo_pos_.get(), vbo_norm_.get(), vbo_color_.get()); + + // drawer for simple old-school g1 rendering + drawer_ = cgogn::make_unique(); + drawer_rend_ = drawer_->generate_renderer(); + update_bb(); +} + +void Viewer::update_bb() +{ + cgogn::geometry::compute_AABB(vertex_position_, bb_); + + drawer_->new_list(); + drawer_->line_width_aa(2.0); + drawer_->begin(GL_LINE_LOOP); + drawer_->color3f(1.0,1.0,1.0); + drawer_->vertex3f(bb_.min()[0],bb_.min()[1],bb_.min()[2]); + drawer_->vertex3f(bb_.max()[0],bb_.min()[1],bb_.min()[2]); + drawer_->vertex3f(bb_.max()[0],bb_.max()[1],bb_.min()[2]); + drawer_->vertex3f(bb_.min()[0],bb_.max()[1],bb_.min()[2]); + drawer_->vertex3f(bb_.min()[0],bb_.max()[1],bb_.max()[2]); + drawer_->vertex3f(bb_.max()[0],bb_.max()[1],bb_.max()[2]); + drawer_->vertex3f(bb_.max()[0],bb_.min()[1],bb_.max()[2]); + drawer_->vertex3f(bb_.min()[0],bb_.min()[1],bb_.max()[2]); + drawer_->end(); + drawer_->begin(GL_LINES); + drawer_->color3f(1.0,1.0,1.0); + drawer_->vertex3f(bb_.min()[0],bb_.min()[1],bb_.min()[2]); + drawer_->vertex3f(bb_.min()[0],bb_.max()[1],bb_.min()[2]); + drawer_->vertex3f(bb_.min()[0],bb_.min()[1],bb_.max()[2]); + drawer_->vertex3f(bb_.min()[0],bb_.max()[1],bb_.max()[2]); + drawer_->vertex3f(bb_.max()[0],bb_.min()[1],bb_.min()[2]); + drawer_->vertex3f(bb_.max()[0],bb_.min()[1],bb_.max()[2]); + drawer_->vertex3f(bb_.max()[0],bb_.max()[1],bb_.min()[2]); + drawer_->vertex3f(bb_.max()[0],bb_.max()[1],bb_.max()[2]); + drawer_->end(); + drawer_->end_list(); +} + +int main(int argc, char** argv) +{ + std::string surface_mesh; + if (argc < 2) + { + cgogn_log_info("simple_viewer") << "USAGE: " << argv[0] << " [filename]"; + surface_mesh = std::string(DEFAULT_MESH_PATH) + std::string("off/aneurysm_3D.off"); + cgogn_log_info("simple_viewer") << "Using default mesh \"" << surface_mesh << "\"."; + } + else + surface_mesh = std::string(argv[1]); + + QApplication application(argc, argv); + qoglviewer::init_ogl_context(); + + // Instantiate the viewer. + Viewer viewer; + viewer.setWindowTitle("simpleViewer"); + viewer.import(surface_mesh); + viewer.show(); + + // Run main loop. + return application.exec(); +} diff --git a/cgogn/geometry/functions/area.h b/cgogn/geometry/functions/area.h index fe041b63..e0728388 100644 --- a/cgogn/geometry/functions/area.h +++ b/cgogn/geometry/functions/area.h @@ -21,8 +21,8 @@ * * *******************************************************************************/ -#ifndef GEOMETRY_FUNCTIONS_AREA_H_ -#define GEOMETRY_FUNCTIONS_AREA_H_ +#ifndef CGOGN_GEOMETRY_FUNCTIONS_AREA_H_ +#define CGOGN_GEOMETRY_FUNCTIONS_AREA_H_ namespace cgogn { @@ -43,4 +43,4 @@ inline typename VEC3_T::Scalar triangle_area(const VEC3_T& p1, const VEC3_T& p2, } // namespace cgogn -#endif // GEOMETRY_FUNCTIONS_AREA_H_ +#endif // CGOGN_GEOMETRY_FUNCTIONS_AREA_H_ diff --git a/cgogn/geometry/functions/basics.h b/cgogn/geometry/functions/basics.h index 225cd7a9..86772ccb 100644 --- a/cgogn/geometry/functions/basics.h +++ b/cgogn/geometry/functions/basics.h @@ -21,10 +21,11 @@ * * *******************************************************************************/ -#ifndef GEOMETRY_FUNCTIONS_BASICS_H_ -#define GEOMETRY_FUNCTIONS_BASICS_H_ +#ifndef CGOGN_GEOMETRY_FUNCTIONS_BASICS_H_ +#define CGOGN_GEOMETRY_FUNCTIONS_BASICS_H_ #include +#include namespace cgogn { @@ -43,11 +44,35 @@ inline void normalize_safe(VEC3& v) const Scalar norm2 = v.squaredNorm(); if (norm2 > Scalar(0)) - v/=std::sqrt(norm2); + v /= std::sqrt(norm2); +} + +/** + * @brief cosinus of the angle formed by 2 vectors + */ +template +typename VEC::Scalar cos_angle(const VEC& a, const VEC& b) +{ + using Scalar = typename VEC::Scalar; + + Scalar na2 = a.squaredNorm(); + Scalar nb2 = b.squaredNorm(); + + Scalar res = a.dot(b) / std::sqrt(na2 * nb2); + return std::max(Scalar(-1), std::min(res, Scalar(1))); +} + +/** + * @brief angle formed by 2 vectors + */ +template +typename VEC::Scalar angle(const VEC& a, const VEC& b) +{ + return std::acos(cos_angle(a, b)); } } // namespace geometry } // namespace cgogn -#endif // GEOMETRY_FUNCTIONS_BASICS_H_ +#endif // CGOGN_GEOMETRY_FUNCTIONS_BASICS_H_ diff --git a/cgogn/geometry/functions/distance.h b/cgogn/geometry/functions/distance.h index e10b5cc1..e69ec7b0 100644 --- a/cgogn/geometry/functions/distance.h +++ b/cgogn/geometry/functions/distance.h @@ -21,10 +21,10 @@ * * *******************************************************************************/ -#ifndef GEOMETRY_FUNCTIONS_DISTANCE_H_ -#define GEOMETRY_FUNCTIONS_DISTANCE_H_ +#ifndef CGOGN_GEOMETRY_FUNCTIONS_DISTANCE_H_ +#define CGOGN_GEOMETRY_FUNCTIONS_DISTANCE_H_ -#include +#include namespace cgogn { @@ -74,4 +74,4 @@ inline typename VEC3_T::Scalar squared_distance_line_point(const VEC3_T& A, cons } // namespace cgogn -#endif // GEOMETRY_FUNCTIONS_DISTANCE_H_ +#endif // CGOGN_GEOMETRY_FUNCTIONS_DISTANCE_H_ diff --git a/cgogn/geometry/functions/inclusion.h b/cgogn/geometry/functions/inclusion.h index 691b3712..df3c4eda 100644 --- a/cgogn/geometry/functions/inclusion.h +++ b/cgogn/geometry/functions/inclusion.h @@ -21,11 +21,11 @@ * * *******************************************************************************/ -#ifndef GEOMETRY_INCLUSION_H_ -#define GEOMETRY_INCLUSION_H_ +#ifndef CGOGN_GEOMETRY_INCLUSION_H_ +#define CGOGN_GEOMETRY_INCLUSION_H_ -#include -#include +#include +#include namespace cgogn { @@ -62,4 +62,4 @@ inline bool in_triangle(const VEC3_T& P, const VEC3_T& Ta, const VEC3_T& Tb, co } // namespace cgogn -#endif // GEOMETRY_INCLUSION_H_ +#endif // CGOGN_GEOMETRY_INCLUSION_H_ diff --git a/cgogn/geometry/functions/intersection.h b/cgogn/geometry/functions/intersection.h index a6ec5633..ce4d5b74 100644 --- a/cgogn/geometry/functions/intersection.h +++ b/cgogn/geometry/functions/intersection.h @@ -21,8 +21,10 @@ * * *******************************************************************************/ -#ifndef GEOMETRY_FUNCTIONS_INTERSECTION_H_ -#define GEOMETRY_FUNCTIONS_INTERSECTION_H_ +#ifndef CGOGN_GEOMETRY_FUNCTIONS_INTERSECTION_H_ +#define CGOGN_GEOMETRY_FUNCTIONS_INTERSECTION_H_ + +#include namespace cgogn { @@ -30,6 +32,14 @@ namespace cgogn namespace geometry { +/** + * \todo geometric predicate : move it to a specific location with other geometric predicates + */ +template +bool in_sphere(const VEC3_T& point, const VEC3_T& center, const typename VEC3_T::Scalar& radius) +{ + return (point - center).norm() < radius; +} template bool intersection_ray_triangle(const VEC3_T& P, const VEC3_T& Dir, const VEC3_T& Ta, const VEC3_T& Tb, const VEC3_T& Tc, VEC3_T* inter=nullptr) @@ -92,10 +102,37 @@ bool intersection_ray_triangle(const VEC3_T& P, const VEC3_T& Dir, const VEC3_T& } +/** + * \param[in] center the position of the center of the sphere. + * \param[in] radius the radius of the sphere + * \param[in] p1 first point of the edge + * \param[in] p2 second point of the edge + * \param[out] alpha size of the edge inside the sphere + */ +template +bool intersection_sphere_edge( + const VEC3_T& center, + const typename VEC3_T::Scalar& radius, + const VEC3_T& p1, + const VEC3_T& p2, + typename VEC3_T::Scalar& alpha) +{ + using Scalar = typename VEC3_T::Scalar; + if(cgogn::geometry::in_sphere(p1, center, radius) && !cgogn::geometry::in_sphere(p2, center, radius)) + { + VEC3_T p = p1 - center; + VEC3_T qminusp = p2 - center - p; + Scalar s = p.dot(qminusp); + Scalar n2 = qminusp.squaredNorm(); + alpha = (- s + std::sqrt(s*s + n2 * (radius*radius - p.squaredNorm()))) / n2; + return true ; + } + return false ; +} } // namespace geometry } // namespace cgogn -#endif // GEOMETRY_FUNCTIONS_INTERSECTION_H_ +#endif // CGOGN_GEOMETRY_FUNCTIONS_INTERSECTION_H_ diff --git a/cgogn/geometry/functions/normal.h b/cgogn/geometry/functions/normal.h index 350ef675..01decc30 100644 --- a/cgogn/geometry/functions/normal.h +++ b/cgogn/geometry/functions/normal.h @@ -21,8 +21,8 @@ * * *******************************************************************************/ -#ifndef GEOMETRY_FUNCTIONS_NORMAL_H_ -#define GEOMETRY_FUNCTIONS_NORMAL_H_ +#ifndef CGOGN_GEOMETRY_FUNCTIONS_NORMAL_H_ +#define CGOGN_GEOMETRY_FUNCTIONS_NORMAL_H_ namespace cgogn { @@ -43,4 +43,4 @@ inline VEC3_T triangle_normal(const VEC3_T& p1, const VEC3_T& p2, const VEC3_T& } // namespace cgogn -#endif // GEOMETRY_FUNCTIONS_NORMAL_H_ +#endif // CGOGN_GEOMETRY_FUNCTIONS_NORMAL_H_ diff --git a/cgogn/geometry/functions/orientation.h b/cgogn/geometry/functions/orientation.h index daf595aa..e64c9af4 100644 --- a/cgogn/geometry/functions/orientation.h +++ b/cgogn/geometry/functions/orientation.h @@ -21,10 +21,10 @@ * * *******************************************************************************/ -#ifndef GEOMETRY_ORIENTATION_H_ -#define GEOMETRY_ORIENTATION_H_ +#ifndef CGOGN_GEOMETRY_ORIENTATION_H_ +#define CGOGN_GEOMETRY_ORIENTATION_H_ -#include +#include namespace cgogn { @@ -65,4 +65,4 @@ Orientation3D test_orientation_3D(const VEC3_T& P, const VEC3_T& N, const VEC3_T } // namespace cgogn -#endif // GEOMETRY_ORIENTATION_H_ +#endif // CGOGN_GEOMETRY_ORIENTATION_H_ diff --git a/cgogn/geometry/tests/CMakeLists.txt b/cgogn/geometry/tests/CMakeLists.txt index 00f45778..b346a46f 100644 --- a/cgogn/geometry/tests/CMakeLists.txt +++ b/cgogn/geometry/tests/CMakeLists.txt @@ -2,10 +2,13 @@ project(cgogn_geometry_test LANGUAGES CXX ) +find_package(cgogn_geometry REQUIRED) +find_package(cgogn_io REQUIRED) + set(SOURCE_FILES types/vec_test.cpp types/plane_3d_test.cpp - types/bounding_box_test.cpp + types/aabb_test.cpp functions/area_test.cpp functions/normal_test.cpp @@ -21,7 +24,7 @@ add_definitions("-DCGOGN_TEST_MESHES_PATH=${CMAKE_SOURCE_DIR}/data/meshes/") add_executable(${PROJECT_NAME} ${SOURCE_FILES}) -target_link_libraries(cgogn_geometry_test gtest cgogn_geometry cgogn_io) +target_link_libraries(cgogn_geometry_test gtest ${cgogn_geometry_LIBRARIES} ${cgogn_io_LIBRARIES}) target_include_directories(cgogn_geometry_test PRIVATE ${CMAKE_SOURCE_DIR}/thirdparty/googletest-master/googletest/include) link_directories(${CMAKE_SOURCE_DIR}/thirdparty/googletest-master/googletest/lib) diff --git a/cgogn/geometry/tests/algos/algos_test.cpp b/cgogn/geometry/tests/algos/algos_test.cpp index 56f6c489..5f19c361 100644 --- a/cgogn/geometry/tests/algos/algos_test.cpp +++ b/cgogn/geometry/tests/algos/algos_test.cpp @@ -21,16 +21,16 @@ * * *******************************************************************************/ -#include +#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include -#include +#include #include #include @@ -48,7 +48,7 @@ using VecTypes = testing::Types; using CMap2 = cgogn::CMap2; using Dart = cgogn::Dart; template -using VertexAttributeHandler = CMap2::VertexAttributeHandler; +using VertexAttribute = CMap2::VertexAttribute; using Vertex = CMap2::Vertex; using Edge = CMap2::Edge; using Face = CMap2::Face; @@ -63,7 +63,7 @@ protected : { using Scalar = typename cgogn::geometry::vector_traits::Scalar; - VertexAttributeHandler vertex_position = this->map2_.template get_attribute("position"); + VertexAttribute vertex_position = this->map2_.template get_attribute("position"); Scalar alpha = 0; Face f = map2_.add_face(n); map2_.foreach_incident_vertex(f, [&] (Vertex v) @@ -79,7 +79,7 @@ TYPED_TEST_CASE(Algos_TEST, VecTypes); TYPED_TEST(Algos_TEST, TriangleArea) { using Scalar = typename cgogn::geometry::vector_traits::Scalar; - VertexAttributeHandler vertex_position = this->map2_.template add_attribute("position"); + VertexAttribute vertex_position = this->map2_.template add_attribute("position"); this->add_polygone(3); Dart t; this->map2_.foreach_dart_until([&t] (Dart d) { t = d; return false; }); @@ -92,7 +92,7 @@ TYPED_TEST(Algos_TEST, TriangleArea) TYPED_TEST(Algos_TEST, QuadArea) { using Scalar = typename cgogn::geometry::vector_traits::Scalar; - VertexAttributeHandler vertex_position = this->map2_.template add_attribute("position"); + VertexAttribute vertex_position = this->map2_.template add_attribute("position"); this->add_polygone(4); Dart q; this->map2_.foreach_dart_until([&q] (Dart d) { q = d; return false; }); @@ -103,7 +103,7 @@ TYPED_TEST(Algos_TEST, QuadArea) TYPED_TEST(Algos_TEST, TriangleCentroid) { using Scalar = typename cgogn::geometry::vector_traits::Scalar; - VertexAttributeHandler vertex_position = this->map2_.template add_attribute("position"); + VertexAttribute vertex_position = this->map2_.template add_attribute("position"); this->add_polygone(3); Dart t; this->map2_.foreach_dart_until([&t] (Dart d) { t = d; return false; }); @@ -117,7 +117,7 @@ TYPED_TEST(Algos_TEST, TriangleCentroid) TYPED_TEST(Algos_TEST, QuadCentroid) { using Scalar = typename cgogn::geometry::vector_traits::Scalar; - VertexAttributeHandler vertex_position = this->map2_.template add_attribute("position"); + VertexAttribute vertex_position = this->map2_.template add_attribute("position"); this->add_polygone(4); Dart q; this->map2_.foreach_dart_until([&q] (Dart d) { q = d; return false; }); @@ -130,7 +130,7 @@ TYPED_TEST(Algos_TEST, QuadCentroid) TYPED_TEST(Algos_TEST, TriangleNormal) { using Scalar = typename cgogn::geometry::vector_traits::Scalar; - VertexAttributeHandler vertex_position = this->map2_.template add_attribute("position"); + VertexAttribute vertex_position = this->map2_.template add_attribute("position"); this->add_polygone(3); Dart t; this->map2_.foreach_dart_until([&t] (Dart d) { t = d; return false; }); @@ -149,7 +149,7 @@ TYPED_TEST(Algos_TEST, TriangleNormal) TYPED_TEST(Algos_TEST, QuadNormal) { using Scalar = typename cgogn::geometry::vector_traits::Scalar; - VertexAttributeHandler vertex_position = this->map2_.template add_attribute("position"); + VertexAttribute vertex_position = this->map2_.template add_attribute("position"); this->add_polygone(4); Dart q; this->map2_.foreach_dart_until([&q] (Dart d) { q = d; return false; }); @@ -163,7 +163,7 @@ TYPED_TEST(Algos_TEST, QuadNormal) TYPED_TEST(Algos_TEST, EarTriangulation) { using Scalar = typename cgogn::geometry::vector_traits::Scalar; - VertexAttributeHandler vertex_position = this->map2_.template add_attribute("position"); + VertexAttribute vertex_position = this->map2_.template add_attribute("position"); Face f = this->map2_.add_face(5); cgogn::Dart d = f.dart; diff --git a/cgogn/geometry/tests/functions/area_test.cpp b/cgogn/geometry/tests/functions/area_test.cpp index b40c10ae..f3656bc9 100644 --- a/cgogn/geometry/tests/functions/area_test.cpp +++ b/cgogn/geometry/tests/functions/area_test.cpp @@ -21,10 +21,10 @@ * * *******************************************************************************/ -#include -#include -#include -#include +#include +#include +#include +#include #include diff --git a/cgogn/geometry/tests/functions/distance_test.cpp b/cgogn/geometry/tests/functions/distance_test.cpp index 22f2bd4e..ef15f2e6 100644 --- a/cgogn/geometry/tests/functions/distance_test.cpp +++ b/cgogn/geometry/tests/functions/distance_test.cpp @@ -21,11 +21,11 @@ * * *******************************************************************************/ -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include diff --git a/cgogn/geometry/tests/functions/intersection_test.cpp b/cgogn/geometry/tests/functions/intersection_test.cpp index e8a14d15..69e80c0e 100644 --- a/cgogn/geometry/tests/functions/intersection_test.cpp +++ b/cgogn/geometry/tests/functions/intersection_test.cpp @@ -21,10 +21,10 @@ * * *******************************************************************************/ -#include -#include -#include -#include +#include +#include +#include +#include #include diff --git a/cgogn/geometry/tests/functions/normal_test.cpp b/cgogn/geometry/tests/functions/normal_test.cpp index a8c7545c..972355bc 100644 --- a/cgogn/geometry/tests/functions/normal_test.cpp +++ b/cgogn/geometry/tests/functions/normal_test.cpp @@ -21,11 +21,11 @@ * * *******************************************************************************/ -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include diff --git a/cgogn/geometry/tests/types/bounding_box_test.cpp b/cgogn/geometry/tests/types/aabb_test.cpp similarity index 70% rename from cgogn/geometry/tests/types/bounding_box_test.cpp rename to cgogn/geometry/tests/types/aabb_test.cpp index 39566189..bf82e77f 100644 --- a/cgogn/geometry/tests/types/bounding_box_test.cpp +++ b/cgogn/geometry/tests/types/aabb_test.cpp @@ -21,36 +21,38 @@ * * *******************************************************************************/ -#include -#include -#include +#include +#include +#include #include -using StdArrayf = cgogn::geometry::Vec_T>; -using StdArrayd = cgogn::geometry::Vec_T>; +using namespace cgogn::numerics; + +using StdArrayf = cgogn::geometry::Vec_T>; +using StdArrayd = cgogn::geometry::Vec_T>; using EigenVec3f = Eigen::Vector3f; using EigenVec3d = Eigen::Vector3d; using VecTypes = testing::Types; template -class BoundingBox_TEST : public testing::Test +class AABB_TEST : public testing::Test { protected : - cgogn::geometry::BoundingBox bb_; + cgogn::geometry::AABB bb_; }; -TYPED_TEST_CASE(BoundingBox_TEST, VecTypes ); +TYPED_TEST_CASE(AABB_TEST, VecTypes ); -TEST(BoundingBox_TEST, NameOfType) +TEST(AABB_TEST, NameOfType) { - EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::BoundingBox()), "cgogn::geometry::BoundingBox>>"); - EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::BoundingBox()), "cgogn::geometry::BoundingBox>"); - EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::BoundingBox()), "cgogn::geometry::BoundingBox>>"); - EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::BoundingBox()), "cgogn::geometry::BoundingBox>"); + EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::AABB()), "cgogn::geometry::AABB>>"); + EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::AABB()), "cgogn::geometry::AABB>"); + EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::AABB()), "cgogn::geometry::AABB>>"); + EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::AABB()), "cgogn::geometry::AABB>"); } -TYPED_TEST(BoundingBox_TEST, Basics) +TYPED_TEST(AABB_TEST, Basics) { using Scalar = typename cgogn::geometry::vector_traits::Scalar; @@ -66,7 +68,7 @@ TYPED_TEST(BoundingBox_TEST, Basics) EXPECT_EQ(this->bb_.center(), TypeParam({Scalar(0), Scalar(0), Scalar(0)})); } -TYPED_TEST(BoundingBox_TEST, testing) +TYPED_TEST(AABB_TEST, testing) { using Scalar = typename cgogn::geometry::vector_traits::Scalar; @@ -76,18 +78,18 @@ TYPED_TEST(BoundingBox_TEST, testing) EXPECT_TRUE(this->bb_.contains(TypeParam({Scalar(1), Scalar(1), Scalar(1)}))); - cgogn::geometry::BoundingBox bb2; + cgogn::geometry::AABB bb2; bb2.add_point(TypeParam({Scalar(0), Scalar(0), Scalar(0)})); bb2.add_point(TypeParam({Scalar(4), Scalar(5), Scalar(2)})); EXPECT_TRUE(this->bb_.intersects(bb2)); - cgogn::geometry::BoundingBox bb3; + cgogn::geometry::AABB bb3; bb3.add_point(TypeParam({Scalar(0), Scalar(0), Scalar(0)})); bb3.add_point(TypeParam({Scalar(1), Scalar(1), Scalar(1)})); EXPECT_TRUE(this->bb_.contains(bb3)); - EXPECT_TRUE(this->bb_.ray_intersect(TypeParam({Scalar(-9), Scalar(-9), Scalar(-9)}), TypeParam({Scalar(1), Scalar(1), Scalar(1)}))); - EXPECT_FALSE(this->bb_.ray_intersect(TypeParam({Scalar(-9), Scalar(-9), Scalar(-9)}), TypeParam({Scalar(1), Scalar(-1), Scalar(0)}))); +// EXPECT_TRUE(this->bb_.ray_intersect(TypeParam({Scalar(-9), Scalar(-9), Scalar(-9)}), TypeParam({Scalar(1), Scalar(1), Scalar(1)}))); +// EXPECT_FALSE(this->bb_.ray_intersect(TypeParam({Scalar(-9), Scalar(-9), Scalar(-9)}), TypeParam({Scalar(1), Scalar(-1), Scalar(0)}))); } diff --git a/cgogn/geometry/tests/types/plane_3d_test.cpp b/cgogn/geometry/tests/types/plane_3d_test.cpp index b9234c98..cfdc392c 100644 --- a/cgogn/geometry/tests/types/plane_3d_test.cpp +++ b/cgogn/geometry/tests/types/plane_3d_test.cpp @@ -21,13 +21,16 @@ * * *******************************************************************************/ -#include -#include +#include +#include +#include #include -using StdArrayf = cgogn::geometry::Vec_T>; -using StdArrayd = cgogn::geometry::Vec_T>; +using namespace cgogn::numerics; + +using StdArrayf = cgogn::geometry::Vec_T>; +using StdArrayd = cgogn::geometry::Vec_T>; using EigenVec3f = Eigen::Vector3f; using EigenVec3d = Eigen::Vector3d; using VecTypes = testing::Types; @@ -40,9 +43,9 @@ TYPED_TEST_CASE(Plane3D_TEST, VecTypes ); TEST(Plane3D_TEST, NameOfType) { - EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::Plane3D(StdArrayf(),0)), "cgogn::geometry::Plane3D>>"); + EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::Plane3D(StdArrayf(),0)), "cgogn::geometry::Plane3D>>"); EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::Plane3D(EigenVec3f(),0)), "cgogn::geometry::Plane3D>"); - EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::Plane3D(StdArrayd(),0)), "cgogn::geometry::Plane3D>>"); + EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::Plane3D(StdArrayd(),0)), "cgogn::geometry::Plane3D>>"); EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::Plane3D(EigenVec3d(),0)), "cgogn::geometry::Plane3D>"); } diff --git a/cgogn/geometry/tests/types/vec_test.cpp b/cgogn/geometry/tests/types/vec_test.cpp index a61de2e3..341b34a1 100644 --- a/cgogn/geometry/tests/types/vec_test.cpp +++ b/cgogn/geometry/tests/types/vec_test.cpp @@ -21,14 +21,17 @@ * * *******************************************************************************/ -#include -#include -#include +#include +#include +#include +#include #include -using StdArrayf = cgogn::geometry::Vec_T>; -using StdArrayd = cgogn::geometry::Vec_T>; +using namespace cgogn::numerics; + +using StdArrayf = cgogn::geometry::Vec_T>; +using StdArrayd = cgogn::geometry::Vec_T>; using EigenVec3f = Eigen::Vector3f; using EigenVec3d = Eigen::Vector3d; using VecTypes = testing::Types; @@ -42,9 +45,9 @@ TYPED_TEST_CASE(VEC_OP_TEST, VecTypes ); TEST(VEC_OP_TEST, CGOGN_Typename) { - EXPECT_EQ(cgogn::name_of_type(StdArrayf()),"cgogn::geometry::Vec_T>"); + EXPECT_EQ(cgogn::name_of_type(StdArrayf()),"cgogn::geometry::Vec_T>"); EXPECT_EQ(cgogn::name_of_type(EigenVec3f()), "Eigen::Matrix"); - EXPECT_EQ(cgogn::name_of_type(StdArrayd()),"cgogn::geometry::Vec_T>"); + EXPECT_EQ(cgogn::name_of_type(StdArrayd()),"cgogn::geometry::Vec_T>"); EXPECT_EQ(cgogn::name_of_type(EigenVec3d()), "Eigen::Matrix"); } diff --git a/cgogn/geometry/types/bounding_box.cpp b/cgogn/geometry/types/aabb.cpp similarity index 84% rename from cgogn/geometry/types/bounding_box.cpp rename to cgogn/geometry/types/aabb.cpp index c7e19fb5..e1cf435a 100644 --- a/cgogn/geometry/types/bounding_box.cpp +++ b/cgogn/geometry/types/aabb.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_GEOMETRY_DLL_EXPORT -#define GEOMETRY_BOUNDING_BOX_CPP_ +#define CGOGN_GEOMETRY_TYPES_AABB_CPP_ -#include +#include namespace cgogn { @@ -32,10 +32,10 @@ namespace cgogn namespace geometry { -template class CGOGN_GEOMETRY_API BoundingBox; -template class CGOGN_GEOMETRY_API BoundingBox; -template class CGOGN_GEOMETRY_API BoundingBox>>; -template class CGOGN_GEOMETRY_API BoundingBox>>; +template class CGOGN_GEOMETRY_API AABB; +template class CGOGN_GEOMETRY_API AABB; +template class CGOGN_GEOMETRY_API AABB>>; +template class CGOGN_GEOMETRY_API AABB>>; } // namespace geometry diff --git a/cgogn/geometry/types/bounding_box.h b/cgogn/geometry/types/aabb.h similarity index 57% rename from cgogn/geometry/types/bounding_box.h rename to cgogn/geometry/types/aabb.h index 2bd1efb9..b84c1265 100644 --- a/cgogn/geometry/types/bounding_box.h +++ b/cgogn/geometry/types/aabb.h @@ -21,16 +21,16 @@ * * *******************************************************************************/ -#ifndef GEOMETRY_TYPES_BOUNDING_BOX_H_ -#define GEOMETRY_TYPES_BOUNDING_BOX_H_ +#ifndef CGOGN_GEOMETRY_TYPES_AABB_H_ +#define CGOGN_GEOMETRY_TYPES_AABB_H_ #include #include -#include +#include -#include -#include +#include +#include namespace cgogn { @@ -38,16 +38,18 @@ namespace cgogn namespace geometry { +/** + * Axis-Aligned Bounding Box + */ template -class BoundingBox +class AABB { - static_assert(vector_traits::SIZE == 3ul, "The size of the vector must be equal to 3."); public: using Vec = VEC_T; using Scalar = typename vector_traits::Scalar; - using Self = BoundingBox; + using Self = AABB; static const uint32 dim_ = vector_traits::SIZE; private: @@ -61,12 +63,12 @@ class BoundingBox /* CONSTRUCTORS */ /**********************************************/ - BoundingBox() : + AABB() : initialized_(false) {} // initialize the bounding box with one first point - BoundingBox(const Vec& p) : + AABB(const Vec& p) : initialized_(true), p_min_(p), p_max_(p) @@ -78,25 +80,25 @@ class BoundingBox Vec& min() { - cgogn_message_assert(initialized_, "Bounding box not initialized"); + cgogn_message_assert(initialized_, "Axis-Aligned Bounding box not initialized"); return p_min_; } const Vec& min() const { - cgogn_message_assert(initialized_, "Bounding box not initialized"); + cgogn_message_assert(initialized_, "Axis-Aligned Bounding box not initialized"); return p_min_; } Vec& max() { - cgogn_message_assert(initialized_, "Bounding box not initialized"); + cgogn_message_assert(initialized_, "Axis-Aligned Bounding box not initialized"); return p_max_; } const Vec& max() const { - cgogn_message_assert(initialized_, "Bounding box not initialized"); + cgogn_message_assert(initialized_, "Axis-Aligned Bounding box not initialized"); return p_max_; } @@ -108,7 +110,7 @@ class BoundingBox Scalar max_size() const { - cgogn_message_assert(initialized_, "Bounding box not initialized"); + cgogn_message_assert(initialized_, "Axis-Aligned Bounding box not initialized"); Scalar max = p_max_[0] - p_min_[0]; for(uint32 i = 1; i < dim_; ++i) { @@ -121,7 +123,7 @@ class BoundingBox Scalar min_size() const { - cgogn_message_assert(initialized_, "Bounding box not initialized"); + cgogn_message_assert(initialized_, "Axis-Aligned Bounding box not initialized"); Scalar min = p_max_[0] - p_min_[0]; for(uint32 i = 1; i < dim_; ++i) { @@ -134,19 +136,19 @@ class BoundingBox Vec diag() const { - cgogn_message_assert(initialized_, "Bounding box not initialized"); + cgogn_message_assert(initialized_, "Axis-Aligned Bounding box not initialized"); return p_max_ - p_min_; } Scalar diag_size() const { - cgogn_message_assert(initialized_, "Bounding box not initialized"); + cgogn_message_assert(initialized_, "Axis-Aligned Bounding box not initialized"); return Scalar((p_max_ - p_min_).norm()); } Vec center() const { - cgogn_message_assert(initialized_, "Bounding box not initialized"); + cgogn_message_assert(initialized_, "Axis-Aligned Bounding box not initialized"); Vec center = (p_max_ + p_min_) / Scalar(2); return center; } @@ -157,13 +159,13 @@ class BoundingBox } - // reinitialize the bounding box + // reinitialize the axis-aligned bounding box void reset() { initialized_ = false; } - // add a point to the bounding box + // add a point to the axis-aligned bounding box void add_point(const Vec& p) { if(!initialized_) @@ -184,10 +186,10 @@ class BoundingBox } } - // return true if bb intersects the bounding box - bool intersects(const BoundingBox& bb) const + // return true if bb intersects the axis-aligned bounding box + bool intersects(const AABB& bb) const { - cgogn_message_assert(initialized_, "Bounding box not initialized"); + cgogn_message_assert(initialized_, "Axis-Aligned Bounding box not initialized"); Vec bbmin = bb.min(); Vec bbmax = bb.max(); for(uint32 i = 0; i < dim_; ++i) @@ -201,9 +203,9 @@ class BoundingBox } // fusion with the given bounding box - void fusion(const BoundingBox& bb) + void fusion(const AABB& bb) { - cgogn_message_assert(initialized_, "Bounding box not initialized"); + cgogn_message_assert(initialized_, "Axis-Aligned Bounding box not initialized"); Vec bbmin = bb.min(); Vec bbmax = bb.max(); for(uint32 i = 0; i < dim_; ++i) @@ -218,7 +220,7 @@ class BoundingBox // return true if the point belongs strictly to a bounding box bool contains(const Vec& p) const { - cgogn_message_assert(initialized_, "Bounding box not initialized"); + cgogn_message_assert(initialized_, "Axis-Aligned Bounding box not initialized"); for(uint32 i = 0; i < dim_; ++i) { if(p_min_[i] > p[i]) @@ -231,16 +233,16 @@ class BoundingBox // return true if the bounding box belongs strictly to a bounding box - bool contains(const BoundingBox& bb) const + bool contains(const AABB& bb) const { - cgogn_message_assert(initialized_, "Bounding box not initialized"); + cgogn_message_assert(initialized_, "Axis-Aligned Bounding box not initialized"); return this->contains(bb.min()) && this->contains(bb.max()); } // scale the bounding box void scale(Scalar size) { - cgogn_message_assert(initialized_, "Bounding box not initialized"); + cgogn_message_assert(initialized_, "Axis-Aligned Bounding box not initialized"); p_min_ *= size; p_max_ *= size; } @@ -248,77 +250,77 @@ class BoundingBox // 0-centered scale of the bounding box void centered_scale(Scalar size) { - cgogn_message_assert(initialized_, "Bounding box not initialized"); + cgogn_message_assert(initialized_, "Axis-Aligned Bounding box not initialized"); Vec center = (p_min_ + p_max_) / Scalar(2); p_min_ = ((p_min_ - center) * size) + center; p_max_ = ((p_max_ - center) * size) + center; } - // test if bb is intersected by a ray - bool ray_intersect(const Vec& P, const Vec& V) const - { - if (!cgogn::almost_equal_relative(V[2], Scalar(0))) - { - Vec Q = P + ((p_min_[2] - P[2]) / V[2]) * V; - if ((Q[0] < p_max_[0]) && (Q[0] > p_min_[0]) && (Q[1] < p_max_[1]) && (Q[1] > p_min_[1])) - return true; - Q = P + ((p_max_[2] - P[2]) / V[2]) * V; - if ((Q[0] < p_max_[0]) && (Q[0] > p_min_[0]) && (Q[1] < p_max_[1]) && (Q[1] > p_min_[1])) - return true; - } - - if (!cgogn::almost_equal_relative(V[1], Scalar(0))) - { - Vec Q = P + ((p_min_[1] - P[1]) / V[1]) * V; - if ((Q[0] < p_max_[0]) && (Q[0] > p_min_[0]) && (Q[2] < p_max_[2]) && (Q[2] > p_min_[2])) - return true; - Q = P + ((p_max_[1] - P[1]) / V[1]) * V; - if ((Q[0] < p_max_[0]) && (Q[0] > p_min_[0]) && (Q[2] < p_max_[2]) && (Q[2] > p_min_[2])) - return true; - } - - if (!cgogn::almost_equal_relative(V[0], Scalar(0))) - { - Vec Q = P + ((p_min_[0] - P[0]) / V[0]) * V; - if ((Q[1] < p_max_[1]) && (Q[1] > p_min_[1]) && (Q[2] < p_max_[2]) && (Q[2] > p_min_[2])) - return true; - Q = P + ((p_max_[0] - P[0]) / V[0]) * V; - if ((Q[1] < p_max_[1]) && (Q[1] > p_min_[1]) && (Q[2] < p_max_[2]) && (Q[2] > p_min_[2])) - return true; - } - - return false; - } +// // test if bb is intersected by a ray +// bool ray_intersect(const Vec& P, const Vec& V) const +// { +// if (!cgogn::almost_equal_relative(V[2], Scalar(0))) +// { +// Vec Q = P + ((p_min_[2] - P[2]) / V[2]) * V; +// if ((Q[0] < p_max_[0]) && (Q[0] > p_min_[0]) && (Q[1] < p_max_[1]) && (Q[1] > p_min_[1])) +// return true; +// Q = P + ((p_max_[2] - P[2]) / V[2]) * V; +// if ((Q[0] < p_max_[0]) && (Q[0] > p_min_[0]) && (Q[1] < p_max_[1]) && (Q[1] > p_min_[1])) +// return true; +// } + +// if (!cgogn::almost_equal_relative(V[1], Scalar(0))) +// { +// Vec Q = P + ((p_min_[1] - P[1]) / V[1]) * V; +// if ((Q[0] < p_max_[0]) && (Q[0] > p_min_[0]) && (Q[2] < p_max_[2]) && (Q[2] > p_min_[2])) +// return true; +// Q = P + ((p_max_[1] - P[1]) / V[1]) * V; +// if ((Q[0] < p_max_[0]) && (Q[0] > p_min_[0]) && (Q[2] < p_max_[2]) && (Q[2] > p_min_[2])) +// return true; +// } + +// if (!cgogn::almost_equal_relative(V[0], Scalar(0))) +// { +// Vec Q = P + ((p_min_[0] - P[0]) / V[0]) * V; +// if ((Q[1] < p_max_[1]) && (Q[1] > p_min_[1]) && (Q[2] < p_max_[2]) && (Q[2] > p_min_[2])) +// return true; +// Q = P + ((p_max_[0] - P[0]) / V[0]) * V; +// if ((Q[1] < p_max_[1]) && (Q[1] > p_min_[1]) && (Q[2] < p_max_[2]) && (Q[2] > p_min_[2])) +// return true; +// } + +// return false; +// } static std::string cgogn_name_of_type() { - return std::string("cgogn::geometry::BoundingBox<") + name_of_type(Vec()) + std::string(">"); + return std::string("cgogn::geometry::AABB<") + name_of_type(Vec()) + std::string(">"); } }; template -std::ostream& operator<<(std::ostream& out, const BoundingBox& bb) +std::ostream& operator<<(std::ostream& out, const AABB& bb) { out << bb.min() << " " << bb.max(); return out; } template -std::istream& operator>>(std::istream& in, BoundingBox& bb) +std::istream& operator>>(std::istream& in, AABB& bb) { in >> bb.min() >> bb.max(); return in; } -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(GEOMETRY_BOUNDING_BOX_CPP_)) -extern template class CGOGN_GEOMETRY_API BoundingBox; -extern template class CGOGN_GEOMETRY_API BoundingBox; -extern template class CGOGN_GEOMETRY_API BoundingBox>>; -extern template class CGOGN_GEOMETRY_API BoundingBox>>; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(GEOMETRY_BOUNDING_BOX_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_GEOMETRY_TYPES_AABB_CPP_)) +extern template class CGOGN_GEOMETRY_API AABB; +extern template class CGOGN_GEOMETRY_API AABB; +extern template class CGOGN_GEOMETRY_API AABB>>; +extern template class CGOGN_GEOMETRY_API AABB>>; +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_GEOMETRY_TYPES_AABB_CPP_)) } // namespace geometry } // namespace cgogn -#endif // GEOMETRY_TYPES_BOUNDING_BOX_H_ +#endif // CGOGN_GEOMETRY_TYPES_AABB_H_ diff --git a/cgogn/geometry/types/eigen.h b/cgogn/geometry/types/eigen.h index a06c6551..f7f85564 100644 --- a/cgogn/geometry/types/eigen.h +++ b/cgogn/geometry/types/eigen.h @@ -21,10 +21,10 @@ * * *******************************************************************************/ -#ifndef GEOMETRY_TYPES_EIGEN_H_ -#define GEOMETRY_TYPES_EIGEN_H_ +#ifndef CGOGN_GEOMETRY_TYPES_EIGEN_H_ +#define CGOGN_GEOMETRY_TYPES_EIGEN_H_ -#include +#include CGOGN_PRAGMA_EIGEN_REMOVE_WARNINGS_ON #include CGOGN_PRAGMA_EIGEN_REMOVE_WARNINGS_OFF @@ -39,4 +39,4 @@ namespace geometry } // namespace cgogn -#endif // GEOMETRY_TYPES_EIGEN_H_ +#endif // CGOGN_GEOMETRY_TYPES_EIGEN_H_ diff --git a/cgogn/geometry/types/geometry_traits.h b/cgogn/geometry/types/geometry_traits.h index 0e3762f5..32b0b829 100644 --- a/cgogn/geometry/types/geometry_traits.h +++ b/cgogn/geometry/types/geometry_traits.h @@ -21,14 +21,14 @@ * * *******************************************************************************/ -#ifndef GEOMETRY_TYPES_GEOMETRY_TRAITS_H_ -#define GEOMETRY_TYPES_GEOMETRY_TRAITS_H_ +#ifndef CGOGN_GEOMETRY_TYPES_GEOMETRY_TRAITS_H_ +#define CGOGN_GEOMETRY_TYPES_GEOMETRY_TRAITS_H_ #include -#include +#include -#include -#include +#include +#include namespace cgogn { @@ -42,7 +42,7 @@ struct vector_traits // specialization 1 : cgogn::geometry::Vec_T with a fixed-size array template -struct vector_traits>> +struct vector_traits>> { static const std::size_t SIZE = Size; using Scalar = Scalar_; @@ -50,7 +50,7 @@ struct vector_traits>> // specialization 2 : Eigen::Vector template -struct vector_traits> +struct vector_traits> { static const std::size_t SIZE = Rows; using Scalar = Scalar_; @@ -78,25 +78,32 @@ struct nb_components_traits {}; template -struct nb_components_traits::value || std::is_floating_point::value >::type > +struct nb_components_traits::value || std::is_floating_point::value>::type> { const static uint32 value = 1u; }; template -struct nb_components_traits>> +struct nb_components_traits>> { const static uint32 value = size; }; template -struct nb_components_traits> +struct nb_components_traits> { const static uint32 value = Rows; }; + +template ::value > 1)>::type* = nullptr> +void set_zero(T& t) { t.setZero(); } + +template ::value == 1)>::type* = nullptr> +void set_zero(T& t) { t = 0; } + } // namespace geometry } // namespace cgogn -#endif // GEOMETRY_TYPES_GEOMETRY_TRAITS_H_ +#endif // CGOGN_GEOMETRY_TYPES_GEOMETRY_TRAITS_H_ diff --git a/cgogn/core/utils/thread_barrier.h b/cgogn/geometry/types/obb.cpp similarity index 63% rename from cgogn/core/utils/thread_barrier.h rename to cgogn/geometry/types/obb.cpp index bad3396b..74f7e9a1 100644 --- a/cgogn/core/utils/thread_barrier.h +++ b/cgogn/geometry/types/obb.cpp @@ -1,7 +1,6 @@ /******************************************************************************* * CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * -* version 0.1 * -* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * * * * This library is free software; you can redistribute it and/or modify it * * under the terms of the GNU Lesser General Public License as published by the * @@ -22,59 +21,22 @@ * * *******************************************************************************/ -#ifndef CORE_UTILS_THREAD_BARRIER_H_ -#define CORE_UTILS_THREAD_BARRIER_H_ +#define CGOGN_GEOMETRY_DLL_EXPORT +#define CGOGN_GEOMETRY_TYPES_OBB_CPP_ -#include -#include -#include +#include namespace cgogn { -/** -* Implementation of simple counter barrier (rdv) -* for c++11 std::thread -*/ -class Barrier +namespace geometry { -private: - uint32 init_count_; - uint32 count_; - uint32 generation_; - - std::mutex protect_; - std::condition_variable cond_; +template class CGOGN_GEOMETRY_API OBB; +template class CGOGN_GEOMETRY_API OBB; +//template class CGOGN_GEOMETRY_API OBB>>; +//template class CGOGN_GEOMETRY_API OBB>>; -public: - - /** - * constructor - * @param count number of threads to syncronize - */ - inline Barrier(uint32 count) : - init_count_(count), - count_(count), - generation_(0) - {} - - inline void wait() - { - std::unique_lock lock(protect_); - uint32 gen = generation_; - - if (--count_ == 0) - { - ++generation_; - count_ = init_count_; - cond_.notify_all(); - } - else - cond_.wait(lock, [this, gen] () { return gen != generation_; }); - } -}; +} // namespace geometry } // namespace cgogn - -#endif // CORE_UTILS_THREAD_BARRIER_H_ diff --git a/cgogn/geometry/types/obb.h b/cgogn/geometry/types/obb.h new file mode 100644 index 00000000..277085a2 --- /dev/null +++ b/cgogn/geometry/types/obb.h @@ -0,0 +1,137 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef CGOGN_GEOMETRY_TYPES_OBB_H_ +#define CGOGN_GEOMETRY_TYPES_OBB_H_ + +#include +#include + +#include + +#include +#include + +namespace cgogn +{ + +namespace geometry +{ + +/** + * Object Bounding Box + */ +template +class OBB +{ + +public: + + using Vec = VEC_T; + using Scalar = typename vector_traits::Scalar; + using Self = OBB; + static const uint32 dim_ = vector_traits::SIZE; + +private: + //center point of this OBB + Vec center_; + Vec extension_; + + //the axes defining the OBB + Eigen::Matrix axes_; + + bool initialized_; + +public: + /**********************************************/ + /* CONSTRUCTORS */ + /**********************************************/ + + OBB() : + initialized_(false) + {} + + + // reinitialize the axis-aligned bounding box + void reset() + { + initialized_ = false; + } + + const Vec& center() const + { + return center_; + } + + void center(const Vec& c) + { + center_ = c; + } + + const Vec& extension() const + { + return extension_; + } + + void extension(const Vec& e) + { + extension_ = e; + } + + const Eigen::Matrix& axis() const + { + return axes_; + } + + void axis(const Eigen::Matrix& a) + { + axes_ = a; + } + + void edges(std::array& e) + { + for(int i=0 ; i < 8 ; ++i) + { + e[i] = center_ + (i&1?1:-1)*extension_[0]*axes_.col(0) + (i&2?1:-1)*extension_[1]*axes_.col(1) + (i&4?1:-1)*extension_[2]*axes_.col(2); + } + } + + static std::string cgogn_name_of_type() + { + return std::string("cgogn::geometry::OBB<") + name_of_type(Vec()) + std::string(">"); + } + +}; + +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_GEOMETRY_TYPES_OBB_CPP_)) +extern template class CGOGN_GEOMETRY_API OBB; +extern template class CGOGN_GEOMETRY_API OBB; +//extern template class CGOGN_GEOMETRY_API OBB>>; +//extern template class CGOGN_GEOMETRY_API OBB>>; +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_GEOMETRY_TYPES_OBB_CPP_)) + +} // namespace geometry + +} // namespace cgogn + +#endif // CGOGN_GEOMETRY_TYPES_OBB_H_ diff --git a/cgogn/geometry/types/plane_3d.cpp b/cgogn/geometry/types/plane_3d.cpp index b7aecd53..0ca5e0ad 100644 --- a/cgogn/geometry/types/plane_3d.cpp +++ b/cgogn/geometry/types/plane_3d.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_GEOMETRY_DLL_EXPORT -#define GEOMETRY_TYPES_PLANE_3D_CPP_ +#define CGOGN_GEOMETRY_TYPES_PLANE_3D_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/geometry/types/plane_3d.h b/cgogn/geometry/types/plane_3d.h index 1682b184..86f59be4 100644 --- a/cgogn/geometry/types/plane_3d.h +++ b/cgogn/geometry/types/plane_3d.h @@ -21,16 +21,16 @@ * * *******************************************************************************/ -#ifndef GEOMETRY_TYPES_PLANE_3D_H_ -#define GEOMETRY_TYPES_PLANE_3D_H_ +#ifndef CGOGN_GEOMETRY_TYPES_PLANE_3D_H_ +#define CGOGN_GEOMETRY_TYPES_PLANE_3D_H_ #include #include -#include +#include -#include -#include +#include +#include namespace cgogn { @@ -138,15 +138,15 @@ class Plane3D Scalar d_; }; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(GEOMETRY_TYPES_PLANE_3D_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_GEOMETRY_TYPES_PLANE_3D_CPP_)) extern template class CGOGN_GEOMETRY_API Plane3D; extern template class CGOGN_GEOMETRY_API Plane3D; extern template class CGOGN_GEOMETRY_API Plane3D>>; extern template class CGOGN_GEOMETRY_API Plane3D>>; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(GEOMETRY_TYPES_PLANE_3D_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_GEOMETRY_TYPES_PLANE_3D_CPP_)) } // namespace geometry } // namespace cgogn -#endif // GEOMETRY_TYPES_PLANE_3D_H_ +#endif // CGOGN_GEOMETRY_TYPES_PLANE_3D_H_ diff --git a/cgogn/geometry/types/vec.cpp b/cgogn/geometry/types/vec.cpp index b0c36a13..74539daa 100644 --- a/cgogn/geometry/types/vec.cpp +++ b/cgogn/geometry/types/vec.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_GEOMETRY_DLL_EXPORT -#define GEOMETRY_TYPES_VEC_CPP_ +#define CGOGN_GEOMETRY_TYPES_VEC_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/geometry/types/vec.h b/cgogn/geometry/types/vec.h index 1dee8481..0aecb53f 100644 --- a/cgogn/geometry/types/vec.h +++ b/cgogn/geometry/types/vec.h @@ -21,18 +21,18 @@ * * *******************************************************************************/ -#ifndef GEOMETRY_TYPES_VEC_H_ -#define GEOMETRY_TYPES_VEC_H_ +#ifndef CGOGN_GEOMETRY_TYPES_VEC_H_ +#define CGOGN_GEOMETRY_TYPES_VEC_H_ #include #include #include #include -#include -#include +#include +#include -#include +#include namespace cgogn { @@ -195,7 +195,6 @@ class Vec_T return v / r; } - inline const Scalar dot(const Self& v) const { Scalar r{0}; @@ -260,18 +259,42 @@ class Vec_T return o; } + inline std::size_t size() const + { + return data_.size(); + } + inline auto begin() const ->decltype(std::declval().begin()) + { + return data_.begin(); + } + + inline auto begin() ->decltype(std::declval().begin()) + { + return data_.begin(); + } + + inline auto end() const ->decltype(std::declval().end()) + { + return data_.end(); + } + + inline auto end() ->decltype(std::declval().end()) + { + return data_.end(); + } + private: Container data_; }; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(GEOMETRY_TYPES_VEC_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_GEOMETRY_TYPES_VEC_CPP_)) extern template class CGOGN_GEOMETRY_API Vec_T>; extern template class CGOGN_GEOMETRY_API Vec_T>; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(GEOMETRY_TYPES_VEC_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_GEOMETRY_TYPES_VEC_CPP_)) } // namespace geometry } // namespace cgogn -#endif // GEOMETRY_TYPES_VEC_H_ +#endif // CGOGN_GEOMETRY_TYPES_VEC_H_ diff --git a/cgogn/io/CMakeLists.txt b/cgogn/io/CMakeLists.txt index b964c229..1f9f3746 100644 --- a/cgogn/io/CMakeLists.txt +++ b/cgogn/io/CMakeLists.txt @@ -3,6 +3,11 @@ project(cgogn_io ) find_package(ZLIB) +find_package(cgogn_core REQUIRED) +find_package(cgogn_geometry REQUIRED) +find_package(ply REQUIRED) +find_package(lm6 REQUIRED) +find_package(tinyxml2 REQUIRED) set(HEADER_FILES surface_import.h @@ -24,6 +29,7 @@ set(HEADER_FILES tetgen_io.h nastran_io.h tet_io.h + volume_export.h ) set(SOURCE_FILES @@ -54,27 +60,21 @@ target_include_directories(${PROJECT_NAME} PUBLIC $ $ $ - $ + $ ) if (${ZLIB_FOUND}) - target_compile_definitions(${PROJECT_NAME} PUBLIC -DZLIB_CONST) - target_compile_definitions(${PROJECT_NAME} PUBLIC -DCGOGN_WITH_ZLIB) + target_compile_definitions(${PROJECT_NAME} PUBLIC "-DZLIB_CONST") + target_compile_definitions(${PROJECT_NAME} PUBLIC "-DCGOGN_WITH_ZLIB") + target_link_libraries(${PROJECT_NAME} ${ZLIB_LIBRARIES}) endif() -target_link_libraries(${PROJECT_NAME} tinyxml2 cgogn_core cgogn_geometry ply lm6 ${ZLIB_LIBRARIES}) +target_link_libraries(${PROJECT_NAME} ${cgogn_core_LIBRARIES} ${cgogn_geometry_LIBRARIES} ${ply_LIBRARIES} ${lm6_LIBRARIES} ${tinyxml2_LIBRARIES}) -install(DIRECTORY . - DESTINATION include/cgogn/io - FILES_MATCHING PATTERN "*.h" -) +file(GLOB HEADERS "." "*.h") +install(FILES ${HEADERS} + DESTINATION include/cgogn/io) -install(TARGETS ${PROJECT_NAME} - EXPORT ${PROJECT_NAME}Targets - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib -) +cgogn_create_package("${CGOGN_SOURCE_DIR}" "include") add_subdirectory(mesh_generation) -add_subdirectory(examples) diff --git a/cgogn/io/c_locale.h b/cgogn/io/c_locale.h index 6ecf636b..f93617f9 100644 --- a/cgogn/io/c_locale.h +++ b/cgogn/io/c_locale.h @@ -21,13 +21,13 @@ * * *******************************************************************************/ -#ifndef IO_C_LOCALE_H_ -#define IO_C_LOCALE_H_ +#ifndef CGOGN_IO_C_LOCALE_H_ +#define CGOGN_IO_C_LOCALE_H_ #include #include -#include +#include namespace cgogn { @@ -58,4 +58,4 @@ class Scoped_C_Locale } // namespace cgogn -#endif // IO_C_LOCALE_H_ +#endif // CGOGN_IO_C_LOCALE_H_ diff --git a/cgogn/io/data_io.cpp b/cgogn/io/data_io.cpp index abafe937..ec86e0fb 100644 --- a/cgogn/io/data_io.cpp +++ b/cgogn/io/data_io.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_IO_DLL_EXPORT -#define IO_DATA_IO_CPP_ +#define CGOGN_IO_DATA_IO_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/io/data_io.h b/cgogn/io/data_io.h index 2aaaf987..57e8b602 100644 --- a/cgogn/io/data_io.h +++ b/cgogn/io/data_io.h @@ -21,19 +21,19 @@ * * *******************************************************************************/ -#ifndef IO_DATA_IO_H_ -#define IO_DATA_IO_H_ +#ifndef CGOGN_IO_DATA_IO_H_ +#define CGOGN_IO_DATA_IO_H_ #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include -#include +#include namespace cgogn { @@ -409,11 +409,11 @@ std::unique_ptr> DataInputGen::newDataIO(co return std::unique_ptr>(); } -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_DATA_IO_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_DATA_IO_CPP_)) extern template class CGOGN_IO_API DataInputGen; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_DATA_IO_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_DATA_IO_CPP_)) } // namespace io } // namespace cgogn -#endif // IO_DATA_IO_H_ +#endif // CGOGN_IO_DATA_IO_H_ diff --git a/cgogn/io/dll.h b/cgogn/io/dll.h index 445d0858..4503d09b 100644 --- a/cgogn/io/dll.h +++ b/cgogn/io/dll.h @@ -21,8 +21,8 @@ * * *******************************************************************************/ -#ifndef IO_DLL_H_ -#define IO_DLL_H_ +#ifndef CGOGN_IO_DLL_H_ +#define CGOGN_IO_DLL_H_ /** * \brief Linkage declaration for CGOGN symbols. @@ -37,4 +37,4 @@ #define CGOGN_IO_API #endif -#endif // IO_DLL_H_ +#endif // CGOGN_IO_DLL_H_ diff --git a/cgogn/io/examples/CMakeLists.txt b/cgogn/io/examples/CMakeLists.txt index 91f26de1..1105bd5a 100644 --- a/cgogn/io/examples/CMakeLists.txt +++ b/cgogn/io/examples/CMakeLists.txt @@ -3,13 +3,16 @@ cmake_minimum_required(VERSION 3.0 FATAL_ERROR) project(cgogn_io_examples LANGUAGES CXX ) +find_package(cgogn_core REQUIRED) +find_package(cgogn_io REQUIRED) + set(CGOGN_TEST_PREFIX "test_") set(CGOGN_TEST_MESHES_PATH "${CMAKE_SOURCE_DIR}/data/meshes/") add_definitions("-DCGOGN_TEST_MESHES_PATH=${CGOGN_TEST_MESHES_PATH}") add_executable(cmap2_import cmap2_import.cpp) -target_link_libraries(cmap2_import cgogn_core cgogn_io) +target_link_libraries(cmap2_import ${cgogn_core_LIBRARIES} ${cgogn_io_LIBRARIES}) add_executable(cmap3_import cmap3_import.cpp) -target_link_libraries(cmap3_import cgogn_core cgogn_io) +target_link_libraries(cmap3_import ${cgogn_core_LIBRARIES} ${cgogn_io_LIBRARIES}) diff --git a/cgogn/io/examples/cmap2_import.cpp b/cgogn/io/examples/cmap2_import.cpp index 1724e662..d8802761 100644 --- a/cgogn/io/examples/cmap2_import.cpp +++ b/cgogn/io/examples/cmap2_import.cpp @@ -3,10 +3,10 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) @@ -23,9 +23,9 @@ using Vec3 = Eigen::Vector3d; //using Vec3 = cgogn::geometry::Vec_T>; template -using VertexAttributeHandler = Map2::VertexAttributeHandler; +using VertexAttribute = Map2::VertexAttribute; template -using FaceAttributeHandler = Map2::FaceAttributeHandler; +using FaceAttribute = Map2::FaceAttribute; int main(int argc, char** argv) { @@ -61,20 +61,21 @@ int main(int argc, char** argv) nb_darts_2 += n; cgogn_log_info("cmap2_import")<< "nb darts // -> " << nb_darts_2; - VertexAttributeHandler vertex_position = map.get_attribute("position"); - VertexAttributeHandler vertex_normal = map.add_attribute("normal"); - FaceAttributeHandler face_normal = map.add_attribute("normal"); + VertexAttribute vertex_position = map.get_attribute("position"); + VertexAttribute vertex_normal = map.add_attribute("normal"); + FaceAttribute face_normal = map.add_attribute("normal"); cgogn_log_info("cmap2_import") << "Map integrity : " << std::boolalpha << map.check_map_integrity(); uint32 nb_vertices = 0; - cgogn::CellCache vmask(map); - map.foreach_cell([&nb_vertices] (Map2::Vertex) { nb_vertices++; }, vmask); + cgogn::CellCache cache(map); + cache.build(); + map.foreach_cell([&nb_vertices] (Map2::Vertex) { nb_vertices++; }, cache); cgogn_log_info("cmap2_import") << "nb vertices -> " << nb_vertices; uint32 nb_boundary_faces = 0; - cgogn::BoundaryCache bmask(map); - map.foreach_cell([&nb_boundary_faces] (Map2::Boundary) { nb_boundary_faces++; }, bmask); + cgogn::BoundaryCache bcache(map); + map.foreach_cell([&nb_boundary_faces] (Map2::Boundary) { nb_boundary_faces++; }, bcache); cgogn_log_info("cmap2_import") << "nb boundary faces -> " << nb_boundary_faces; uint32 nb_faces = 0; diff --git a/cgogn/io/examples/cmap3_import.cpp b/cgogn/io/examples/cmap3_import.cpp index d18b4621..aa858090 100644 --- a/cgogn/io/examples/cmap3_import.cpp +++ b/cgogn/io/examples/cmap3_import.cpp @@ -2,8 +2,8 @@ #include #include -#include -#include +#include +#include #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) @@ -16,9 +16,9 @@ using Vec3 = Eigen::Vector3d; //using Vec3 = cgogn::geometry::Vec_T>; template -using VertexAttributeHandler = Map3::VertexAttributeHandler; +using VertexAttribute = Map3::VertexAttribute; template -using FaceAttributeHandler = Map3::FaceAttributeHandler; +using FaceAttribute = Map3::FaceAttribute; int main(int argc, char** argv) @@ -42,7 +42,7 @@ int main(int argc, char** argv) std::chrono::time_point start, end; start = std::chrono::system_clock::now(); - VertexAttributeHandler vertex_position = map.get_attribute("position"); + VertexAttribute vertex_position = map.get_attribute("position"); // map.enable_topo_cache(); // map.enable_topo_cache(); diff --git a/cgogn/io/import_ply_data.cpp b/cgogn/io/import_ply_data.cpp index 3679c39b..da95373d 100644 --- a/cgogn/io/import_ply_data.cpp +++ b/cgogn/io/import_ply_data.cpp @@ -26,9 +26,9 @@ #endif #define CGOGN_IO_DLL_EXPORT -#define IO_IMPORT_PLY_DATA_CPP_ +#define CGOGN_IO_IMPORT_PLY_DATA_CPP_ -#include +#include #include #include #include diff --git a/cgogn/io/import_ply_data.h b/cgogn/io/import_ply_data.h index 74317856..aac746da 100644 --- a/cgogn/io/import_ply_data.h +++ b/cgogn/io/import_ply_data.h @@ -30,8 +30,8 @@ #include #include -#include -#include +#include +#include namespace cgogn { diff --git a/cgogn/io/io_utils.cpp b/cgogn/io/io_utils.cpp index eab1a5b5..3df60a3f 100644 --- a/cgogn/io/io_utils.cpp +++ b/cgogn/io/io_utils.cpp @@ -30,9 +30,9 @@ #include #endif -#include -#include -#include +#include +#include +#include namespace cgogn { @@ -266,6 +266,30 @@ CharArrayBuffer::~CharArrayBuffer() {} IMemoryStream::~IMemoryStream() {} +CGOGN_IO_API bool file_exists(const std::string& filename) +{ + return std::ifstream(filename).good(); +} + +CGOGN_IO_API std::unique_ptr create_file(const std::string& filename) +{ + std::unique_ptr output; + std::string new_filename(filename); + if (file_exists(new_filename)) + { + uint32 i{1u}; + const std::string base_name = cgogn::remove_extension(filename); + do { + new_filename = base_name + "(" + std::to_string(i++) + ")." + cgogn::get_extension(filename); + } while (file_exists(new_filename)); + cgogn_log_warning("create_file") << "The output filename has been changed to \"" << new_filename << "\""; + } + output = cgogn::make_unique(new_filename, std::ios::out); + if (!output->good()) + cgogn_log_warning("create_file") << "Error while opening the file \"" << filename << "\""; + return output; +} + } // namespace io } // namespace cgogn diff --git a/cgogn/io/io_utils.h b/cgogn/io/io_utils.h index 6dea22c3..71b73fda 100644 --- a/cgogn/io/io_utils.h +++ b/cgogn/io/io_utils.h @@ -21,17 +21,17 @@ * * *******************************************************************************/ -#ifndef IO_IO_UTILS_H_ -#define IO_IO_UTILS_H_ +#ifndef CGOGN_IO_IO_UTILS_H_ +#define CGOGN_IO_IO_UTILS_H_ #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include namespace cgogn { @@ -70,9 +70,21 @@ enum DataType DOUBLE, UNKNOWN }; -CGOGN_IO_API FileType get_file_type(const std::string& filename); -CGOGN_IO_API DataType get_data_type(const std::string& type_name); -CGOGN_IO_API std::vector base64_decode(const char* input, std::size_t begin, std::size_t length = std::numeric_limits::max()); + +enum VolumeType +{ + Tetra, + Pyramid, + TriangularPrism, + Hexa, + Connector +}; + +CGOGN_IO_API bool file_exists(const std::string& filename); +CGOGN_IO_API std::unique_ptr create_file(const std::string& filename); +CGOGN_IO_API FileType get_file_type(const std::string& filename); +CGOGN_IO_API DataType get_data_type(const std::string& type_name); +CGOGN_IO_API std::vector base64_decode(const char* input, std::size_t begin, std::size_t length = std::numeric_limits::max()); #ifdef CGOGN_WITH_ZLIB CGOGN_IO_API std::vector zlib_decompress(const char* input, DataType header_type); @@ -91,14 +103,14 @@ inline auto convert(const T&) -> typename std::enable_if -inline auto convert(const T&x) -> typename std::enable_if<(std::is_arithmetic::value || std::is_floating_point::value) && (std::is_arithmetic::value || std::is_floating_point::value),U>::type +inline auto convert(const T&x) -> typename std::enable_if::value && std::is_arithmetic::value,U>::type { return U(x); } // #3 copy component by component if both type have the same number of components (>1) template -inline auto convert(const T& x) -> typename std::enable_if::value && !std::is_floating_point::value && std::is_same< std::integral_constant::value>, std::integral_constant::value>>::value, U>::type +inline auto convert(const T& x) -> typename std::enable_if::value && std::is_same< std::integral_constant::value>, std::integral_constant::value>>::value, U>::type { U res; for(uint32 i = 0u; i < geometry::nb_components_traits::value ; ++i) @@ -108,13 +120,13 @@ inline auto convert(const T& x) -> typename std::enable_if -inline typename std::enable_if::value || std::is_floating_point::value, T>::type swap_endianness(const T& x) +inline typename std::enable_if::value, T>::type swap_endianness(const T& x) { return ::cgogn::swap_endianness(x); } template -inline typename std::enable_if<(!std::is_arithmetic::value) && !std::is_floating_point::value, T>::type swap_endianness(T& x) +inline typename std::enable_if::value, T>::type swap_endianness(T& x) { for (std::size_t i = 0u ; i < geometry::vector_traits::SIZE; ++i) x[i] = ::cgogn::swap_endianness(x[i]); @@ -122,14 +134,14 @@ inline typename std::enable_if<(!std::is_arithmetic::value) && !std::is_float } template -inline typename std::enable_if::value || std::is_floating_point::value, std::istream&>::type parse(std::istream& iss, T& x) +inline typename std::enable_if::value, std::istream&>::type parse(std::istream& iss, T& x) { iss >> x; return iss; } template -inline typename std::enable_if::value && !std::is_floating_point::value, std::istream&>::type parse(std::istream& iss, T& x) +inline typename std::enable_if::value, std::istream&>::type parse(std::istream& iss, T& x) { for (std::size_t i = 0u ; i < geometry::vector_traits::SIZE; ++i) iss >> x[i]; @@ -276,4 +288,4 @@ class CGOGN_IO_API IMemoryStream : public std::istream } // namespace io } // namespace cgogn -#endif // IO_IO_UTILS_H_ +#endif // CGOGN_IO_IO_UTILS_H_ diff --git a/cgogn/io/lm6_io.cpp b/cgogn/io/lm6_io.cpp index e2a0385d..c49bb5c6 100644 --- a/cgogn/io/lm6_io.cpp +++ b/cgogn/io/lm6_io.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_IO_DLL_EXPORT -#define IO_LM6_IO_CPP_ +#define CGOGN_IO_LM6_IO_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/io/lm6_io.h b/cgogn/io/lm6_io.h index 9793a739..e66c72ad 100644 --- a/cgogn/io/lm6_io.h +++ b/cgogn/io/lm6_io.h @@ -21,11 +21,11 @@ * * *******************************************************************************/ -#ifndef IO_LM6_IO_H_ -#define IO_LM6_IO_H_ +#ifndef CGOGN_IO_LM6_IO_H_ +#define CGOGN_IO_LM6_IO_H_ #include -#include +#include namespace cgogn { @@ -66,26 +66,24 @@ class LM6VolumeImport : public VolumeImport const int number_of_pyramids = GmfStatKwd(mesh_index, GmfPyramids); - this->volumes_vertex_indices_.reserve(4*number_of_tetras + 8*number_of_hexas + 6*number_of_prisms + 5*number_of_pyramids); + this->set_nb_vertices(number_of_vertices); + this->set_nb_volumes(number_of_tetras + number_of_hexas + number_of_prisms + number_of_pyramids); - this->nb_vertices_ = number_of_vertices; - this->nb_volumes_ = number_of_tetras + number_of_hexas + number_of_prisms + number_of_pyramids; - this->volumes_types.reserve(this->nb_volumes_); - - if (number_of_vertices == 0 || this->nb_volumes_ == 0u) + if (this->get_nb_vertices() == 0 || this->get_nb_volumes()== 0u) { + cgogn_log_warning("LM6VolumeImport") << "Error while reading the file \"" << filename << "\"."; GmfCloseMesh(mesh_index); clear(); return false; } - ChunkArray* position = this->vertex_attributes_.template add_attribute("position"); - int ref; + ChunkArray* position = this->template get_position_attribute(); + int32 ref; GmfGotoKwd(mesh_index, GmfVertices); - for (int i = 0 ; i < number_of_vertices; ++i) + for (uint32 i = 0u, end = this->get_nb_vertices() ; i < end; ++i) { - uint32 idx = this->vertex_attributes_.template insert_lines<1>(); + uint32 idx = this->insert_line_vertex_container(); std::array v; (void) GmfGetLin(mesh_index, GmfVertices, &v[0],&v[1], &v[2], &ref); position->operator [](idx)[0] = v[0]; @@ -152,15 +150,15 @@ class LM6VolumeImport : public VolumeImport } }; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_LM6_IO_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_LM6_IO_CPP_)) extern template class CGOGN_IO_API LM6VolumeImport; extern template class CGOGN_IO_API LM6VolumeImport; extern template class CGOGN_IO_API LM6VolumeImport>>; extern template class CGOGN_IO_API LM6VolumeImport>>; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_LM6_IO_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_LM6_IO_CPP_)) } // namespace io } // namespace cgogn -#endif // IO_LM6_IO_H_ +#endif // CGOGN_IO_LM6_IO_H_ diff --git a/cgogn/io/map_export.h b/cgogn/io/map_export.h index da35795c..98a49872 100644 --- a/cgogn/io/map_export.h +++ b/cgogn/io/map_export.h @@ -21,8 +21,8 @@ * * *******************************************************************************/ -#ifndef IO_MAP_EXPORT_H_ -#define IO_MAP_EXPORT_H_ +#ifndef CGOGN_IO_MAP_EXPORT_H_ +#define CGOGN_IO_MAP_EXPORT_H_ #include #include @@ -30,10 +30,15 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace cgogn { @@ -41,8 +46,40 @@ namespace cgogn namespace io { -//template -//void export_surface(cgogn::CMap2& cmap2, const std::string& filename); +template +inline std::unique_ptr> newVolumeExport(const std::string& filename); + + +template +inline void export_volume(MAP& map3, const ExportOptions& options); + + + +template +inline void export_volume(MAP& map3, const ExportOptions& options) +{ + auto ve = newVolumeExport(options.filename_); + if (ve) + ve->export_file(map3,options); +} + +template +inline std::unique_ptr > newVolumeExport(const std::string& filename) +{ + const FileType file_type = get_file_type(filename); + switch (file_type) + { +// case FileType::FileType_VTK_LEGACY: + case FileType::FileType_VTU: return make_unique>(); + case FileType::FileType_MSH: return make_unique>(); + case FileType::FileType_NASTRAN: return make_unique>(); + case FileType::FileType_AIMATSHAPE: return make_unique>(); + default: + cgogn_log_warning("newVolumeExport") << "VolumeExport does not handle files with extension \"" << get_extension(filename) << "\"."; + return std::unique_ptr> (); + } +} + /** * @brief export surface in off format @@ -52,7 +89,7 @@ namespace io * @return ok ? */ template -bool export_off(MAP& map, const typename MAP::template VertexAttributeHandler& position, const std::string& filename) +bool export_off(MAP& map, const typename MAP::template VertexAttribute& position, const std::string& filename) { using Vertex = typename MAP::Vertex; using Face = typename MAP::Face; @@ -73,12 +110,12 @@ bool export_off(MAP& map, const typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); + typename MAP::template VertexAttribute ids = map.template add_attribute("indices"); ids.set_all_container_values(UINT_MAX); uint32 count = 0; - map.template foreach_cell([&] (Face f) + map.foreach_cell([&] (Face f) { - map.template foreach_incident_vertex(f, [&] (Vertex v) + map.foreach_incident_vertex(f, [&] (Vertex v) { if (ids[v]==UINT_MAX) { @@ -92,12 +129,12 @@ bool export_off(MAP& map, const typename MAP::template VertexAttributeHandler prim; prim.reserve(20); - map.template foreach_cell([&] (Face f) + map.foreach_cell([&] (Face f) { uint32 valence = 0; prim.clear(); - map.template foreach_incident_vertex(f, [&] (Vertex v) + map.foreach_incident_vertex(f, [&] (Vertex v) { prim.push_back(ids[v]); ++valence; @@ -114,7 +151,6 @@ bool export_off(MAP& map, const typename MAP::template VertexAttributeHandler -bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandler& position, const std::string& filename) +bool export_off_bin(MAP& map, const typename MAP::template VertexAttribute& position, const std::string& filename) { using Vertex = typename MAP::Vertex; using Face = typename MAP::Face; @@ -147,7 +183,7 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle // two pass of traversal to avoid huge buffer (with same performance); // first pass to save positions & store contiguous indices - typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); + typename MAP::template VertexAttribute ids = map.template add_attribute("indices"); ids.set_all_container_values(UINT_MAX); @@ -158,9 +194,9 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle std::vector buffer_pos; buffer_pos.reserve(BUFFER_SZ+3); - map.template foreach_cell([&] (Face f) + map.foreach_cell([&] (Face f) { - map.template foreach_incident_vertex(f, [&] (Vertex v) + map.foreach_incident_vertex(f, [&] (Vertex v) { if (ids[v]==UINT_MAX) { @@ -198,12 +234,12 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle std::vector prim; prim.reserve(20); - map.template foreach_cell([&] (Face f) + map.foreach_cell([&] (Face f) { uint32 valence = 0; prim.clear(); - map.template foreach_incident_vertex(f, [&] (Vertex v) + map.foreach_incident_vertex(f, [&] (Vertex v) { prim.push_back(ids[v]); ++valence; @@ -231,8 +267,6 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle return true; } - - /** * @brief export surface in obj format (positions only) * @param map the map to export @@ -241,7 +275,7 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle * @return ok ? */ template -bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler& position, const std::string& filename) +bool export_obj(MAP& map, const typename MAP::template VertexAttribute& position, const std::string& filename) { using Vertex = typename MAP::Vertex; using Face = typename MAP::Face; @@ -254,24 +288,23 @@ bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); + typename MAP::template VertexAttribute ids = map.template add_attribute("indices"); ids.set_all_container_values(UINT_MAX); uint32 count = 1; - map.template foreach_cell([&] (Face f) + map.foreach_cell([&] (Face f) { - map.template foreach_incident_vertex(f, [&] (Vertex v) + map.foreach_incident_vertex(f, [&] (Vertex v) { - if (ids[v]==UINT_MAX) + if (ids[v] == UINT_MAX) { ids[v] = count++; const VEC3& P = position[v]; - fp <<"v " << P[0] << " " << P[1] << " " << P[2] << std::endl; + fp << "v " << P[0] << " " << P[1] << " " << P[2] << std::endl; } }); }); @@ -280,10 +313,10 @@ bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler prim; prim.reserve(20); - map.template foreach_cell([&] (Face f) + map.foreach_cell([&] (Face f) { fp << "f"; - map.template foreach_incident_vertex(f, [&] (Vertex v) + map.foreach_incident_vertex(f, [&] (Vertex v) { fp << " " << ids[v]; }); @@ -295,8 +328,6 @@ bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler -bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler& position, const typename MAP::template VertexAttributeHandler& normal, const std::string& filename) +bool export_obj(MAP& map, const typename MAP::template VertexAttribute& position, const typename MAP::template VertexAttribute& normal, const std::string& filename) { using Vertex = typename MAP::Vertex; using Face = typename MAP::Face; @@ -318,46 +349,46 @@ bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); + typename MAP::template VertexAttribute ids = map.template add_attribute("indices"); ids.set_all_container_values(UINT_MAX); uint32 count = 1; std::vector indices; indices.reserve(map.template nb_cells()); map.template foreach_cell([&] (Face f) { - map.template foreach_incident_vertex(f, [&] (Vertex v) + map.foreach_incident_vertex(f, [&] (Vertex v) { - if (ids[v]==UINT_MAX) + if (ids[v] == UINT_MAX) { indices.push_back(map.template get_embedding(v)); ids[v] = count++; const VEC3& P = position[v]; - fp <<"v " << P[0] << " " << P[1] << " " << P[2] << std::endl; + fp << "v " << P[0] << " " << P[1] << " " << P[2] << std::endl; } }); }); fp << std::endl << "# normals" << std::endl; // save normals - for (uint32 i: indices) + for (uint32 i : indices) { const VEC3& N = normal[i]; - fp <<"vn " << N[0] << " " << N[1] << " " << N[2] << std::endl; + fp << "vn " << N[0] << " " << N[1] << " " << N[2] << std::endl; } fp << std::endl << "# faces" << std::endl; // second pass to save primitives std::vector prim; prim.reserve(20); - map.template foreach_cell([&] (Face f) + map.foreach_cell([&] (Face f) { fp << "f"; - map.template foreach_incident_vertex(f, [&] (Vertex v) + map.foreach_incident_vertex(f, [&] (Vertex v) { fp << " " << ids[v] << "//" << ids[v]; }); @@ -369,10 +400,8 @@ bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler -bool export_stl_ascii(MAP& map, const typename MAP::template VertexAttributeHandler& position, const std::string& filename) +bool export_stl_ascii(const MAP& map, const typename MAP::template VertexAttribute& position, const std::string& filename) { using Vertex = typename MAP::Vertex; using Face = typename MAP::Face; @@ -385,45 +414,45 @@ bool export_stl_ascii(MAP& map, const typename MAP::template VertexAttributeHand } // set precision for float output - fp<< std::setprecision(12); + fp << std::setprecision(12); fp << "solid" << filename << std::endl; std::vector table_indices; table_indices.reserve(256); - map.template foreach_cell([&] (Face f) + map.foreach_cell([&] (Face f) { if (map.is_triangle(f)) { - VEC3 N = geometry::face_normal(map,f,position); - fp << "facet normal "<< N[0] << " "<< N[1]<< " " << N[2]<< std::endl; - fp << "outer loop"<< std::endl; + VEC3 N = geometry::face_normal(map, f, position); + fp << "facet normal " << N[0] << " " << N[1] << " " << N[2] << std::endl; + fp << "outer loop" << std::endl; map.template foreach_incident_vertex(f, [&] (Vertex v) { const VEC3& P = position[v]; - fp <<"vertex " << P[0] << " " << P[1] << " " << P[2] << std::endl; + fp << "vertex " << P[0] << " " << P[1] << " " << P[2] << std::endl; }); - fp << "endloop"<< std::endl; - fp << "endfacet"<< std::endl; + fp << "endloop" << std::endl; + fp << "endfacet" << std::endl; } else { table_indices.clear(); - cgogn::geometry::compute_ear_triangulation(map,f,position,table_indices); - for(uint32 i=0; i(map, f, position, table_indices); + for(uint32 i = 0; i < table_indices.size(); i += 3) { const VEC3& A = position[table_indices[i]]; const VEC3& B = position[table_indices[i+1]]; const VEC3& C = position[table_indices[i+2]]; VEC3 N = geometry::triangle_normal(A,B,C); - fp << "facet normal "<< N[0] << " "<< N[1]<< " " << N[2]<< std::endl; + fp << "facet normal " << N[0] << " " << N[1] << " " << N[2] << std::endl; fp << "outer loop"<< std::endl; fp << "vertex " << A[0] << " " << A[1] << " " << A[2] << std::endl; fp << "vertex " << B[0] << " " << B[1] << " " << B[2] << std::endl; fp << "vertex " << C[0] << " " << C[1] << " " << C[2] << std::endl; - fp << "endloop"<< std::endl; - fp << "endfacet"<< std::endl; + fp << "endloop" << std::endl; + fp << "endfacet" << std::endl; } } }); @@ -434,12 +463,9 @@ bool export_stl_ascii(MAP& map, const typename MAP::template VertexAttributeHand return true; } - - template -bool export_stl_bin(MAP& map, const typename MAP::template VertexAttributeHandler& position, const std::string& filename) +bool export_stl_bin(const MAP& map, const typename MAP::template VertexAttribute& position, const std::string& filename) { - //UINT8[80] – Header //UINT32 – Number of triangles @@ -492,7 +518,7 @@ bool export_stl_bin(MAP& map, const typename MAP::template VertexAttributeHandle uint32 nb_tri = 0; // write face cutted in triangle if necessary - map.template foreach_cell([&] (Face f) + map.foreach_cell([&] (Face f) { if (map.is_triangle(f)) { @@ -509,7 +535,7 @@ bool export_stl_bin(MAP& map, const typename MAP::template VertexAttributeHandle { table_indices.clear(); cgogn::geometry::compute_ear_triangulation(map,f,position,table_indices); - for(uint32 i=0; i +bool export_vtp( + MAP& map, + const typename MAP::template VertexAttribute& position, + const typename MAP::template VertexAttribute& scalar, + const std::string& filename) +{ + using Vertex = typename MAP::Vertex; + using Face = typename MAP::Face; + + std::ofstream fp(filename.c_str(), std::ios::out); + if (!fp.good()) + { + cgogn_log_warning("export_vtp") << "Unable to open file \"" << filename << "\"."; + return false; + } + + // set precision for real output + fp<< std::setprecision(12); + + fp << "" << std::endl; + fp << "" << std::endl; + fp << "" << std::endl; + fp << "() << "\" NumberOfPolys=\""<< map.template nb_cells() << "\">" << std::endl; + fp << "" << std::endl; + fp << "" << std::endl; + + std::vector scalar_v; + + // first pass to store contiguous indices + typename MAP::template VertexAttribute ids = map.template add_attribute("indices"); + ids.set_all_container_values(UINT_MAX); + uint32 count = 0; + map.template foreach_cell([&] (Face f) + { + map.template foreach_incident_vertex(f, [&] (Vertex v) + { + if (ids[v]==UINT_MAX) + { + ids[v] = count++; + const VEC3& P = position[v]; + fp << P[0] << " " << P[1] << " " << P[2] << std::endl; + scalar_v.push_back(scalar[v]); + } + }); + }); + + fp << "" << std::endl; + fp << "" << std::endl; + + fp << "" << std::endl; + fp << "" << std::endl; + + for(uint32 i = 0 ; i < scalar_v.size() ; ++i) + fp << scalar_v[i] << std::endl; + + fp << "" << std::endl; + fp << "" << std::endl; + + std::vector triangles; + triangles.reserve(2048); + + map.foreach_cell([&] (Face d) + { + uint32 degree = map.codegree(d); + Dart f=d.dart; + switch(degree) + { + case 3: + triangles.push_back(ids[Vertex(f)]); f = map.phi1(f); + triangles.push_back(ids[Vertex(f)]); f = map.phi1(f); + triangles.push_back(ids[Vertex(f)]); + break; + } + }); + + fp << "" << std::endl; + + fp << "" << std::endl; + for (uint32 i = 0; i < triangles.size(); i += 3) + fp << triangles[i] << " " << triangles[i+1] << " " << triangles[i+2] << std::endl; + fp << "" << std::endl; + + fp << "" ; + uint32 offset = 0; + for (uint32 i = 0; i < triangles.size(); i += 3) + { + offset += 3; + if (i%60 ==0) + fp << std::endl; + fp << " " << offset; + } + fp << std::endl << "" << std::endl; + + fp << "" << std::endl; + fp << "" << std::endl; + fp << "" << std::endl; + fp << "" << std::endl; + + map.remove_attribute(ids); + fp.close(); + return true; +} + template std::string nameOfTypePly(const T& v) @@ -548,8 +685,11 @@ template <> inline std::string nameOfTypePly(const float32&) { return "float32"; template <> inline std::string nameOfTypePly(const float64&) { return "float64"; } template -bool export_ply(MAP& map, const typename MAP::template VertexAttributeHandler& position, const std::string& filename) +bool export_ply(MAP& map, const typename MAP::template VertexAttribute& position, const std::string& filename) { + using Vertex = typename MAP::Vertex; + using Face = typename MAP::Face; + std::ofstream fp(filename.c_str(), std::ios::out); if (!fp.good()) { @@ -576,7 +716,7 @@ bool export_ply(MAP& map, const typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); + typename MAP::template VertexAttribute ids = map.template add_attribute("indices"); ids.set_all_container_values(UINT_MAX); uint32 count = 0; map.template foreach_cell([&] (Face f) @@ -619,8 +759,11 @@ bool export_ply(MAP& map, const typename MAP::template VertexAttributeHandler -bool export_ply_bin(MAP& map, const typename MAP::template VertexAttributeHandler& position, const std::string& filename) +bool export_ply_bin(const MAP& map, const typename MAP::template VertexAttribute& position, const std::string& filename) { + using Vertex = typename MAP::Vertex; + using Face = typename MAP::Face; + std::ofstream fp(filename.c_str(), std::ios::out|std::ofstream::binary); if (!fp.good()) { @@ -629,7 +772,7 @@ bool export_ply_bin(MAP& map, const typename MAP::template VertexAttributeHandle } fp << "ply" << std::endl ; - if (internal::cgogn_is_big_endian) + if (cgogn::internal::cgogn_is_big_endian) fp << "format binary_big_endian 1.0" << std::endl ; else fp << "format binary_little_endian 1.0" << std::endl ; @@ -647,7 +790,7 @@ bool export_ply_bin(MAP& map, const typename MAP::template VertexAttributeHandle // two pass of traversal to avoid huge buffer (with same performance); // first pass to save positions & store contiguous indices - typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); + typename MAP::template VertexAttribute ids = map.template add_attribute("indices"); ids.set_all_container_values(UINT_MAX); @@ -727,4 +870,4 @@ bool export_ply_bin(MAP& map, const typename MAP::template VertexAttributeHandle } // namespace cgogn -#endif // IO_MAP_IMPORT_H_ +#endif // CGOGN_IO_MAP_EXPORT_H_ diff --git a/cgogn/io/map_import.h b/cgogn/io/map_import.h index 6a3cc5c5..3c3e3d26 100644 --- a/cgogn/io/map_import.h +++ b/cgogn/io/map_import.h @@ -21,27 +21,27 @@ * * *******************************************************************************/ -#ifndef IO_MAP_IMPORT_H_ -#define IO_MAP_IMPORT_H_ +#ifndef CGOGN_IO_MAP_IMPORT_H_ +#define CGOGN_IO_MAP_IMPORT_H_ #include #include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace cgogn { @@ -126,4 +126,4 @@ inline std::unique_ptr > newVolumeImport(const std::str } // namespace cgogn -#endif // IO_MAP_IMPORT_H_ +#endif // CGOGN_IO_MAP_IMPORT_H_ diff --git a/cgogn/io/mesh_generation/CMakeLists.txt b/cgogn/io/mesh_generation/CMakeLists.txt index 0a556509..dab89875 100644 --- a/cgogn/io/mesh_generation/CMakeLists.txt +++ b/cgogn/io/mesh_generation/CMakeLists.txt @@ -1,6 +1,9 @@ cmake_minimum_required(VERSION 3.0 FATAL_ERROR) find_package(CGAL) +find_package(cgogn_core REQUIRED) +find_package(cgogn_io REQUIRED) +find_package(tet REQUIRED) project(cgogn_io_mesh_generation LANGUAGES CXX @@ -39,9 +42,6 @@ add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) target_include_directories(${PROJECT_NAME} PUBLIC $ - $ ) -target_link_libraries(${PROJECT_NAME} cgogn_core cgogn_io tet ${LIBRARIES}) - -add_subdirectory(examples) +target_link_libraries(${PROJECT_NAME} ${cgogn_core_LIBRARIES} ${cgogn_io_LIBRARIES} ${tet_LIBRARIES} ${LIBRARIES}) diff --git a/cgogn/io/mesh_generation/c3t3_io.cpp b/cgogn/io/mesh_generation/c3t3_io.cpp index d7394da0..b6858d95 100644 --- a/cgogn/io/mesh_generation/c3t3_io.cpp +++ b/cgogn/io/mesh_generation/c3t3_io.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_IO_DLL_EXPORT -#define IO_C3T3_IO_CPP_ +#define CGOGN_IO_C3T3_IO_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/io/mesh_generation/c3t3_io.h b/cgogn/io/mesh_generation/c3t3_io.h index 32d3ae59..1788bf0d 100644 --- a/cgogn/io/mesh_generation/c3t3_io.h +++ b/cgogn/io/mesh_generation/c3t3_io.h @@ -25,7 +25,7 @@ #define IO_C3T3_IO_H_ #include -#include +#include #include #include @@ -78,20 +78,18 @@ class C3T3VolumeImport : public VolumeImport { const Triangulation& triangulation = cpx_.triangulation(); std::map vertices_indices; - ChunkArray* position = this->vertex_attributes_.template add_attribute("position"); + ChunkArray* position = this->template get_position_attribute(); - const unsigned int num_vertices = triangulation.number_of_vertices(); - const unsigned int num_cells = cpx_.number_of_cells_in_complex(); + const uint32 num_vertices = triangulation.number_of_vertices(); + const uint32 num_cells = cpx_.number_of_cells_in_complex(); - this->volumes_nb_vertices_.reserve(num_cells); - this->volumes_vertex_indices_.reserve(4u*num_cells); - this->nb_vertices_ = num_vertices; - this->nb_volumes_ = num_cells; + this->set_nb_volumes(num_cells); + this->set_nb_vertices(num_vertices); for (auto vit = triangulation.finite_vertices_begin(), vend = triangulation.finite_vertices_end(); vit != vend; ++vit) { const auto& P = vit->point(); - const unsigned id = this->vertex_attributes_.template insert_lines<1>(); + const uint32 id = this->insert_line_vertex_container(); vertices_indices[vit] = id; position->operator [](id) = VEC3(Scalar(P.x()), Scalar(P.y()), Scalar(P.z())); } @@ -99,10 +97,10 @@ class C3T3VolumeImport : public VolumeImport for (auto cit = cpx_.cells_in_complex_begin(), cend = cpx_.cells_in_complex_end(); cit != cend; ++cit) this->add_tetra(*position, vertices_indices[cit->vertex(0)], vertices_indices[cit->vertex(1)], vertices_indices[cit->vertex(2)], vertices_indices[cit->vertex(3)], true); - ChunkArray* subdomain_indices = this->volume_attributes_.template add_attribute("subdomain index"); + ChunkArray* subdomain_indices = this->get_volume_attributes_container().template add_attribute("subdomain index"); for (auto cit = cpx_.cells_in_complex_begin(), cend = cpx_.cells_in_complex_end(); cit != cend; ++cit) { - const unsigned id = this->volume_attributes_.template insert_lines<1>(); + const uint32 id = this->get_volume_attributes_container().template insert_lines<1>(); subdomain_indices->operator [](id) = cpx_.subdomain_index(cit); } @@ -112,12 +110,12 @@ class C3T3VolumeImport : public VolumeImport C3T3 cpx_; }; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_C3T3_IO_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_C3T3_IO_CPP_)) extern template class CGOGN_IO_API C3T3VolumeImport; extern template class CGOGN_IO_API C3T3VolumeImport; extern template class CGOGN_IO_API C3T3VolumeImport>>; extern template class CGOGN_IO_API C3T3VolumeImport>>; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_C3T3_IO_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_C3T3_IO_CPP_)) } // namespace io } // namespace cgogn diff --git a/cgogn/io/mesh_generation/examples/CMakeLists.txt b/cgogn/io/mesh_generation/examples/CMakeLists.txt index 6ab26daa..e08d7403 100644 --- a/cgogn/io/mesh_generation/examples/CMakeLists.txt +++ b/cgogn/io/mesh_generation/examples/CMakeLists.txt @@ -4,6 +4,9 @@ project(cgogn_io_mesh_gen_examples LANGUAGES CXX ) +find_package(cgogn_core REQUIRED) +find_package(cgogn_io REQUIRED) + set(CGOGN_TEST_PREFIX "test_") set(CGOGN_TEST_IMAGES_PATH "${CMAKE_SOURCE_DIR}/data/images/") add_definitions("-DCGOGN_TEST_IMAGES_PATH=${CGOGN_TEST_IMAGES_PATH}") @@ -21,8 +24,8 @@ set(SOURCE_FILES if (CGOGN_WITH_CGAL_EXAMPLES) find_package(Boost REQUIRED COMPONENTS program_options) add_executable(map3_from_image ${HEADER_FILES} ${SOURCE_FILES}) - target_link_libraries(map3_from_image cgogn_core cgogn_io_mesh_generation ${Boost_LIBRARIES}) + target_link_libraries(map3_from_image ${cgogn_core_LIBRARIES} cgogn_io_mesh_generation ${Boost_LIBRARIES}) endif() add_executable(map3_from_surface map3_from_surface.cpp) -target_link_libraries(map3_from_surface cgogn_core cgogn_io cgogn_io_mesh_generation) +target_link_libraries(map3_from_surface ${cgogn_core_LIBRARIES} ${cgogn_io_LIBRARIES} cgogn_io_mesh_generation) diff --git a/cgogn/io/mesh_generation/examples/map3_from_image.cpp b/cgogn/io/mesh_generation/examples/map3_from_image.cpp index d2fdb42f..ba12d47e 100644 --- a/cgogn/io/mesh_generation/examples/map3_from_image.cpp +++ b/cgogn/io/mesh_generation/examples/map3_from_image.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include #include "map3_from_image.h" #include "program_options.h" @@ -33,9 +33,9 @@ using Map3 = cgogn::CMap3; using Vec3 = Eigen::Vector3d; template -using VertexAttributeHandler = Map3::VertexAttributeHandler; +using VertexAttribute = Map3::VertexAttribute; template -using FaceAttributeHandler = Map3::FaceAttributeHandler; +using FaceAttribute = Map3::FaceAttribute; namespace cp = CGAL::parameters; namespace cpi = cp::internal; @@ -87,26 +87,29 @@ int main(int argc, char** argv) std::chrono::time_point start, end; start = std::chrono::system_clock::now(); - VertexAttributeHandler vertex_position = map.get_attribute("position"); + VertexAttribute vertex_position = map.get_attribute("position"); + + + cgogn::CellCache cell_cache(map); + cell_cache.template build(); + cell_cache.template build(); + cell_cache.template build(); + cell_cache.template build(); - map.enable_topo_cache(); - map.enable_topo_cache(); - map.enable_topo_cache(); - map.enable_topo_cache(); unsigned int nbw = 0u; map.foreach_cell([&nbw] (Map3::Volume) { ++nbw; - }); + }, cell_cache); unsigned int nbf = 0u; map.foreach_cell([&] (Map3::Face f) { ++nbf; - Vec3 v1 = vertex_position[Map3::Vertex(map.phi1(f.dart))] - vertex_position[Map3::Vertex(f.dart)]; - Vec3 v2 = vertex_position[Map3::Vertex(map.phi_1(f.dart))] - vertex_position[Map3::Vertex(f.dart)]; - }); +// Vec3 v1 = vertex_position[Map3::Vertex(map.phi1(f.dart))] - vertex_position[Map3::Vertex(f.dart)]; +// Vec3 v2 = vertex_position[Map3::Vertex(map.phi_1(f.dart))] - vertex_position[Map3::Vertex(f.dart)]; + }, cell_cache); unsigned int nbv = 0; map.foreach_cell([&] (Map3::Vertex v) @@ -117,22 +120,22 @@ int main(int argc, char** argv) { ++nb_incident; }); - }); + }, cell_cache); unsigned int nbe = 0; map.foreach_cell([&nbe] (Map3::Edge) { ++nbe; - }); + }, cell_cache); - std::cout << "nb vertices -> " << nbv << std::endl; - std::cout << "nb edges -> " << nbe << std::endl; - std::cout << "nb faces -> " << nbf << std::endl; - std::cout << "nb volumes -> " << nbw << std::endl; + cgogn_log_info("map3_from_image") << "nb vertices -> " << nbv; + cgogn_log_info("map3_from_image") << "nb edges -> " << nbe; + cgogn_log_info("map3_from_image") << "nb faces -> " << nbf; + cgogn_log_info("map3_from_image") << "nb volumes -> " << nbw; end = std::chrono::system_clock::now(); std::chrono::duration elapsed_seconds = end - start; - std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n"; + cgogn_log_info("map3_from_image") << "elapsed time: " << elapsed_seconds.count() << "s"; return 0; diff --git a/cgogn/io/mesh_generation/examples/map3_from_image.h b/cgogn/io/mesh_generation/examples/map3_from_image.h index 832ef52e..441cb578 100644 --- a/cgogn/io/mesh_generation/examples/map3_from_image.h +++ b/cgogn/io/mesh_generation/examples/map3_from_image.h @@ -1,11 +1,11 @@ #ifndef IO_MAP3_FROM_IMAGE_H #define IO_MAP3_FROM_IMAGE_H -#include -#include +#include +#include -#include -#include +#include +#include #include diff --git a/cgogn/io/mesh_generation/examples/map3_from_surface.cpp b/cgogn/io/mesh_generation/examples/map3_from_surface.cpp index 4cd57a70..9f38ff84 100644 --- a/cgogn/io/mesh_generation/examples/map3_from_surface.cpp +++ b/cgogn/io/mesh_generation/examples/map3_from_surface.cpp @@ -24,9 +24,11 @@ #include #include -#include -#include -#include +#include +#include +#include +#include +#include using namespace cgogn::numerics; @@ -41,22 +43,24 @@ int main(int argc, char** argv) { std::string surface_path; std::string tetgen_arg; - if (argc < 3) + std::string output_filename; + if (argc < 4) { - cgogn_log_info("map3_from_surface") << "USAGE: " << argv[0] << " [surface_mesh_path] [tetgen_args]"; + cgogn_log_info("map3_from_surface") << "USAGE: " << argv[0] << " [surface_mesh_path] [tetgen_args] [output]"; std::exit(EXIT_FAILURE); } else { surface_path = std::string(argv[1]); tetgen_arg = std::string(argv[2]); + output_filename = std::string(argv[3]); } Map2 map2; std::unique_ptr tetgen_input; { cgogn::io::import_surface(map2, surface_path); - Map2::VertexAttributeHandler vertex_position = map2.get_attribute("position"); + Map2::VertexAttribute vertex_position = map2.get_attribute("position"); tetgen_input = cgogn::io::export_tetgen(map2, vertex_position); } @@ -67,13 +71,19 @@ int main(int argc, char** argv) cgogn::io::TetgenStructureVolumeImport tetgen_import(&tetgen_output); tetgen_import.import_file(""); tetgen_import.create_map(map3); - } + } + Map3::VertexAttribute vertex_position = map3.get_attribute("position"); + Map3::VertexAttribute vertex_test_att = map3.add_attribute("test"); + std::vector> att_vec; + att_vec.push_back(std::make_pair(cgogn::Orbit(Map3::Vertex::ORBIT), std::string("position"))); + att_vec.push_back(std::make_pair(cgogn::Orbit(Map3::Vertex::ORBIT), std::string("test"))); + cgogn::io::export_volume(map3, cgogn::io::ExportOptions(output_filename, att_vec, false)); std::chrono::time_point start, end; start = std::chrono::system_clock::now(); - Map3::VertexAttributeHandler vertex_position = map3.get_attribute("position"); + // map3.enable_topo_cache(); // map3.enable_topo_cache(); diff --git a/cgogn/io/mesh_generation/examples/program_options.cpp b/cgogn/io/mesh_generation/examples/program_options.cpp index 5f2e674f..4cb51d9e 100644 --- a/cgogn/io/mesh_generation/examples/program_options.cpp +++ b/cgogn/io/mesh_generation/examples/program_options.cpp @@ -23,7 +23,7 @@ #include "program_options.h" #include -#include +#include #define DEFAULT_IMAGE_PATH CGOGN_STR(CGOGN_TEST_IMAGES_PATH) diff --git a/cgogn/io/mesh_generation/tetgen_structure_io.cpp b/cgogn/io/mesh_generation/tetgen_structure_io.cpp index dda0c81e..fc952ec6 100644 --- a/cgogn/io/mesh_generation/tetgen_structure_io.cpp +++ b/cgogn/io/mesh_generation/tetgen_structure_io.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_IO_DLL_EXPORT -#define IO_TETGEN_STRUCTURE_IO_CPP +#define CGOGN_IO_TETGEN_STRUCTURE_IO_CPP -#include +#include namespace cgogn { diff --git a/cgogn/io/mesh_generation/tetgen_structure_io.h b/cgogn/io/mesh_generation/tetgen_structure_io.h index 40c7366d..beb516d8 100644 --- a/cgogn/io/mesh_generation/tetgen_structure_io.h +++ b/cgogn/io/mesh_generation/tetgen_structure_io.h @@ -21,13 +21,13 @@ * * *******************************************************************************/ -#ifndef IO_TETGEN_STRUCTURE_IO_H -#define IO_TETGEN_STRUCTURE_IO_H +#ifndef CGOGN_IO_TETGEN_STRUCTURE_IO_H +#define CGOGN_IO_TETGEN_STRUCTURE_IO_H #include -#include -#include +#include +#include #include @@ -58,27 +58,24 @@ class TetgenStructureVolumeImport : public VolumeImport virtual bool import_file_impl(const std::string& /*filename*/) override { - this->nb_vertices_ = volume_->numberofpoints; - this->nb_volumes_ = volume_->numberoftetrahedra; - this->volumes_types.reserve(this->nb_volumes_); - this->volumes_vertex_indices_.reserve(4u*this->nb_volumes_); + this->set_nb_vertices(volume_->numberofpoints); + this->set_nb_volumes(volume_->numberoftetrahedra); - if (this->nb_vertices_ == 0u || this->nb_volumes_ == 0u) + if (this->get_nb_vertices() == 0u || this->get_nb_volumes()== 0u) { + cgogn_log_warning("TetgenStructureVolumeImport") << "Error while importing data."; this->clear(); return false; } - ChunkArray* position = this->vertex_attributes_.template add_attribute("position"); - + ChunkArray* position = this->template get_position_attribute(); //create vertices std::vector vertices_indices; float64* p = volume_->pointlist ; - vertices_indices.reserve(this->nb_vertices_); - for(uint32 i = 0u; i < this->nb_vertices_; ++i) + for(uint32 i = 0u, end = this->get_nb_vertices(); i < end; ++i) { - const unsigned id = this->vertex_attributes_.template insert_lines<1>(); + const unsigned id = this->insert_line_vertex_container(); position->operator [](id) = VEC3(Scalar(p[0]), Scalar(p[1]), Scalar(p[2])); vertices_indices.push_back(id); p += 3 ; @@ -86,7 +83,7 @@ class TetgenStructureVolumeImport : public VolumeImport //create tetrahedrons int* t = volume_->tetrahedronlist ; - for(uint32 i = 0u; i < this->nb_volumes_; ++i) + for(uint32 i = 0u, end = this->get_nb_volumes(); i < end; ++i) { std::array ids; for(uint32 j = 0u; j < 4u; j++) @@ -102,13 +99,15 @@ class TetgenStructureVolumeImport : public VolumeImport }; template -std::unique_ptr export_tetgen(CMap2& map, const typename CMap2::template VertexAttributeHandler& pos) +std::unique_ptr export_tetgen(CMap2& map, const typename CMap2::template VertexAttribute& pos) { using Map = CMap2; using Vertex = typename Map::Vertex; using Face = typename Map::Face; using TetgenReal = REAL; + + map.compact_embedding(Vertex::ORBIT); std::unique_ptr output = make_unique(); // 0-based indexing @@ -119,27 +118,28 @@ std::unique_ptr export_tetgen(CMap2& map, const typename C output->pointlist = new TetgenReal[output->numberofpoints * 3]; //for each vertex - uint32 i = 0u; - map.foreach_cell([&output,&i,&pos](Vertex v) + + map.foreach_cell([&output,&map,&pos](Vertex v) { const VEC3& vec = pos[v]; - output->pointlist[i++] = vec[0]; - output->pointlist[i++] = vec[1]; - output->pointlist[i++] = vec[2]; + const uint32 emb = map.get_embedding(v); + output->pointlist[3u*emb + 0u] = vec[0]; + output->pointlist[3u*emb + 1u] = vec[1]; + output->pointlist[3u*emb + 2u] = vec[2]; }); output->numberoffacets = map.template nb_cells(); output->facetlist = new tetgenio::facet[output->numberoffacets] ; //for each facet - i = 0u; + uint32 i = 0u;i = 0u; map.foreach_cell([&output,&i,&map](Face face) { tetgenio::facet* f = &(output->facetlist[i]); tetgenio::init(f); f->numberofpolygons = 1; - f->polygonlist = new tetgenio::polygon[f->numberofpolygons]; - tetgenio::polygon* p = f->polygonlist; + f->polygonlist = new tetgenio::polygon[1]; + tetgenio::polygon* p = &f->polygonlist[0]; tetgenio::init(p); p->numberofvertices = map.codegree(face); p->vertexlist = new int[p->numberofvertices]; @@ -150,22 +150,20 @@ std::unique_ptr export_tetgen(CMap2& map, const typename C p->vertexlist[j++] = map.get_embedding(v); }); - f->numberofholes = 0; - f->holelist = nullptr; ++i; }); return output; } -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_TETGEN_STRUCTURE_IO_CPP)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_TETGEN_STRUCTURE_IO_CPP)) extern template class CGOGN_IO_API TetgenStructureVolumeImport; extern template class CGOGN_IO_API TetgenStructureVolumeImport; extern template class CGOGN_IO_API TetgenStructureVolumeImport>>; extern template class CGOGN_IO_API TetgenStructureVolumeImport>>; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_TETGEN_STRUCTURE_IO_CPP)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_TETGEN_STRUCTURE_IO_CPP)) } // namespace io } // namespace cgogn -#endif // IO_TETGEN_STRUCTURE_IO_H +#endif // CGOGN_IO_TETGEN_STRUCTURE_IO_H diff --git a/cgogn/io/mesh_io_gen.cpp b/cgogn/io/mesh_io_gen.cpp index 2131fdff..31238b71 100644 --- a/cgogn/io/mesh_io_gen.cpp +++ b/cgogn/io/mesh_io_gen.cpp @@ -26,8 +26,8 @@ #include #include -#include -#include +#include +#include namespace cgogn { diff --git a/cgogn/io/mesh_io_gen.h b/cgogn/io/mesh_io_gen.h index bb58e2d2..3a36ecff 100644 --- a/cgogn/io/mesh_io_gen.h +++ b/cgogn/io/mesh_io_gen.h @@ -21,15 +21,15 @@ * * *******************************************************************************/ -#ifndef IO_MESH_IO_GEN_H_ -#define IO_MESH_IO_GEN_H_ +#ifndef CGOGN_IO_MESH_IO_GEN_H_ +#define CGOGN_IO_MESH_IO_GEN_H_ #include -#include +#include -#include -#include +#include +#include namespace cgogn { @@ -72,4 +72,4 @@ class CGOGN_IO_API MeshImportGen } // namespace cgogn -#endif // IO_MESH_IO_GEN_H_ +#endif // CGOGN_IO_MESH_IO_GEN_H_ diff --git a/cgogn/io/msh_io.cpp b/cgogn/io/msh_io.cpp index 0d804617..3a45e8bf 100644 --- a/cgogn/io/msh_io.cpp +++ b/cgogn/io/msh_io.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_IO_DLL_EXPORT -#define IO_MSH_IO_CPP_ +#define CGOGN_IO_MSH_IO_CPP_ -#include +#include namespace cgogn { @@ -41,5 +41,7 @@ template class CGOGN_IO_API MshVolumeImport; template class CGOGN_IO_API MshVolumeImport>>; template class CGOGN_IO_API MshVolumeImport>>; +template class CGOGN_IO_API MshVolumeExport>; + } // namespace io } // namespace cgogn diff --git a/cgogn/io/msh_io.h b/cgogn/io/msh_io.h index 94afabe9..097fe415 100644 --- a/cgogn/io/msh_io.h +++ b/cgogn/io/msh_io.h @@ -21,15 +21,16 @@ * * *******************************************************************************/ -#ifndef IO_MSH_IO_H_ -#define IO_MSH_IO_H_ +#ifndef CGOGN_IO_MSH_IO_H_ +#define CGOGN_IO_MSH_IO_H_ #include -#include -#include -#include -#include +#include +#include +#include +#include +#include namespace cgogn { @@ -149,20 +150,20 @@ class MshVolumeImport : public MshIO:: inline bool import_legacy_msh_file(std::istream& data_stream) { - ChunkArray* position = this->vertex_attributes_.template add_attribute("position"); + ChunkArray* position = this->template get_position_attribute(); std::map old_new_indices; std::string line; std::string word; line.reserve(512); word.reserve(128); line = this->skip_empty_lines(data_stream); - this->nb_vertices_ = uint32(std::stoul(line)); + this->set_nb_vertices(uint32(std::stoul(line))); - for (uint32 i = 0u; i < this->nb_vertices_; ++i) + for (uint32 i = 0u, end = this->get_nb_vertices(); i < end; ++i) { std::getline(data_stream,line); - const uint32 new_index = this->vertex_attributes_.template insert_lines<1>(); + const uint32 new_index = this->insert_line_vertex_container(); auto& v = position->operator [](new_index); uint32 old_index; std::istringstream iss(line); @@ -178,9 +179,9 @@ class MshVolumeImport : public MshIO:: return false; std::getline(data_stream,line); - this->nb_volumes_ = uint32(std::stoul(line)); + this->set_nb_volumes(uint32(std::stoul(line))); - for (uint32 i = 0u; i < this->nb_volumes_; ++i) + for (uint32 i = 0u, end = this->get_nb_volumes(); i < end; ++i) { std::getline(data_stream,line); int32 elem_number; @@ -221,7 +222,7 @@ class MshVolumeImport : public MshIO:: inline bool import_ascii_msh_file(std::istream& data_stream) { - ChunkArray* position = this->vertex_attributes_.template add_attribute("position"); + ChunkArray* position = this->template get_position_attribute(); std::map old_new_indices; std::string line; std::string word; @@ -236,13 +237,13 @@ class MshVolumeImport : public MshIO:: return false; std::getline(data_stream, line); - this->nb_vertices_ = uint32(std::stoul(line)); + this->set_nb_vertices(uint32(std::stoul(line))); - for (uint32 i = 0u; i < this->nb_vertices_; ++i) + for (uint32 i = 0u, end = this->get_nb_vertices(); i < end ; ++i) { std::getline(data_stream,line); - const uint32 new_index = this->vertex_attributes_.template insert_lines<1>(); + const uint32 new_index = this->insert_line_vertex_container(); auto& v = position->operator [](new_index); uint32 old_index; std::istringstream iss(line); @@ -258,9 +259,9 @@ class MshVolumeImport : public MshIO:: line = this->skip_empty_lines(data_stream); line = this->skip_empty_lines(data_stream); - this->nb_volumes_ = uint32(std::stoul(line)); + this->set_nb_volumes(uint32(std::stoul(line))); - for (uint32 i = 0u; i < this->nb_volumes_; ++i) + for (uint32 i = 0u, end = this->get_nb_volumes(); i < end; ++i) { std::getline(data_stream,line); int32 elem_number; @@ -316,7 +317,7 @@ class MshVolumeImport : public MshIO:: inline bool import_binary_msh_file(std::istream& data_stream) { - ChunkArray* position = this->vertex_attributes_.template add_attribute("position"); + ChunkArray* position = this->template get_position_attribute(); std::map old_new_indices; std::string line; line.reserve(512); @@ -329,15 +330,15 @@ class MshVolumeImport : public MshIO:: return false; std::getline(data_stream, line); - this->nb_vertices_ = uint32(std::stoul(line)); + this->set_nb_vertices(uint32(std::stoul(line))); std::vector buff; - buff.resize(this->nb_vertices_*(4u + 3u* /*this->float_size_*/ sizeof(float64))); + buff.resize(this->get_nb_vertices()*(4u + 3u* /*this->float_size_*/ sizeof(float64))); data_stream.read(&buff[0], buff.size()); for (auto it = buff.begin(), end = buff.end() ; it != end ;) { - const uint32 new_index = this->vertex_attributes_.template insert_lines<1>(); + const uint32 new_index = this->insert_line_vertex_container(); auto& v = position->operator [](new_index); using Scalar = decltype(v[0]); uint32 old_index = *reinterpret_cast(&(*it)); @@ -366,9 +367,9 @@ class MshVolumeImport : public MshIO:: line = this->skip_empty_lines(data_stream); line = this->skip_empty_lines(data_stream); - this->nb_volumes_ = uint32(std::stoul(line)); + this->set_nb_volumes(uint32(std::stoul(line))); - for (uint32 i = 0u; i < this->nb_volumes_;) + for (uint32 i = 0u, end = this->get_nb_volumes(); i < end;) { std::array header_buff; data_stream.read(&header_buff[0], header_buff.size()); @@ -460,7 +461,66 @@ class MshVolumeImport : public MshIO:: } }; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_MSH_IO_CPP_)) +template +class MshVolumeExport : public VolumeExport +{ +public: + using Inherit = VolumeExport; + using Self = MshVolumeExport; + using Map = typename Inherit::Map; + using Vertex = typename Inherit::Vertex; + using Volume = typename Inherit::Volume; + using ChunkArrayGen = typename Inherit::ChunkArrayGen; + + +protected: + virtual void export_file_impl(const Map& map, std::ofstream& output, const ExportOptions& option) override + { + + ChunkArrayGen const* pos = this->get_position_attribute(); + const std::string endianness = cgogn::internal::cgogn_is_little_endian ? "LittleEndian" : "BigEndian"; + const std::string format = (option.binary_?"binary" :"ascii"); + std::string scalar_type = pos->get_nested_type_name(); + scalar_type[0] = std::toupper(scalar_type[0]); + + // 1. vertices + output << "$NOD" << std::endl; + output << map.template nb_cells() << std::endl; + uint32 vertices_counter = 1u; + map.foreach_cell([&](Vertex v) + { + output << vertices_counter++ << " "; + pos->export_element(map.get_embedding(v), output, false); + output << std::endl; + }); + output << "$ENDNOD" << std::endl; + + + // 2. volumes + output << "$ELM" << std::endl; + const auto& nb_vert_vol = this->get_number_of_vertices(); + const uint32 nb_vols = nb_vert_vol.size(); + output << nb_vols << std::endl; + + uint32 cell_counter = 1u; + auto vertices_it = this->get_vertices_of_volumes().begin(); + for (uint32 w = 0u; w < nb_vols; ++w) + { + const uint32 type = (nb_vert_vol[w] == 4u)?4u:(nb_vert_vol[w] == 5u)?7u:(nb_vert_vol[w] == 6u)?6u:5u; + output << cell_counter++ << " " << type <<" 1 1 " << nb_vert_vol[w]<<" "; + for (uint32 i = 0u ; i < nb_vert_vol[w]; ++i) + { + output << *vertices_it + 1u << " "; + ++vertices_it; + } + output << std::endl; + } + output << "$ENDELM" << std::endl; + } +}; + + +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_MSH_IO_CPP_)) extern template class CGOGN_IO_API MshIO; extern template class CGOGN_IO_API MshIO; extern template class CGOGN_IO_API MshIO>>; @@ -470,9 +530,11 @@ extern template class CGOGN_IO_API MshVolumeImport; extern template class CGOGN_IO_API MshVolumeImport>>; extern template class CGOGN_IO_API MshVolumeImport>>; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_MSH_IO_CPP_)) + +extern template class CGOGN_IO_API MshVolumeExport>; +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_MSH_IO_CPP_)) } // namespace io } // namespace cgogn -#endif // IO_MSH_IO_H_ +#endif // CGOGN_IO_MSH_IO_H_ diff --git a/cgogn/io/nastran_io.cpp b/cgogn/io/nastran_io.cpp index 66f6ccb7..c7eab3d7 100644 --- a/cgogn/io/nastran_io.cpp +++ b/cgogn/io/nastran_io.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_IO_DLL_EXPORT -#define IO_NASTRAN_IO_CPP_ +#define CGOGN_IO_NASTRAN_IO_CPP_ -#include +#include namespace cgogn { @@ -39,5 +39,7 @@ template class CGOGN_IO_API NastranVolumeImport; template class CGOGN_IO_API NastranVolumeImport>>; template class CGOGN_IO_API NastranVolumeImport>>; + +template class CGOGN_IO_API NastranVolumeExport>; } // namespace io } // namespace cgogn diff --git a/cgogn/io/nastran_io.h b/cgogn/io/nastran_io.h index e54b1024..7138dffe 100644 --- a/cgogn/io/nastran_io.h +++ b/cgogn/io/nastran_io.h @@ -21,15 +21,18 @@ * * *******************************************************************************/ -#ifndef IO_NASTRAN_IO_H_ -#define IO_NASTRAN_IO_H_ +#ifndef CGOGN_IO_NASTRAN_IO_H_ +#define CGOGN_IO_NASTRAN_IO_H_ #include +#include +#include -#include -#include -#include -#include +#include +#include +#include +#include +#include namespace cgogn { @@ -80,7 +83,7 @@ class NastranVolumeImport : public NastranIO, public VolumeImport* position = this->vertex_attributes_.template add_attribute("position"); + ChunkArray* position = this->template get_position_attribute(); std::string line; line.reserve(512); @@ -95,13 +98,12 @@ class NastranVolumeImport : public NastranIO, public VolumeImportnb_vertices_ = 0u; std::map old_new_ids_map; do { std::string s_v = line.substr(8,8); const uint32 old_index = std::stoi(s_v); - const uint32 new_index = this->vertex_attributes_.template insert_lines<1>(); + const uint32 new_index = this->insert_line_vertex_container(); old_new_ids_map[old_index] = new_index; auto& v = position->operator [](new_index); @@ -114,48 +116,19 @@ class NastranVolumeImport : public NastranIO, public VolumeImportnb_vertices_++; + this->set_nb_vertices(this->get_nb_vertices() + 1u); } while (tag =="GRID"); // reading volumes - this->nb_volumes_ = 0u; do { - std::string s_v = line.substr(0,std::min(line.size(),12ul)); - - if (s_v.compare(0, 5,"CHEXA") == 0) + std::string s_v = line.substr(0,std::min(line.size(),std::size_t(12))); + if (s_v[0] != '$') { - this->nb_volumes_++; - std::array ids; - - s_v = line.substr(24,8); - ids[0] = uint32(std::stoi(s_v)); - s_v = line.substr(32,8); - ids[1] = uint32(std::stoi(s_v)); - s_v = line.substr(40,8); - ids[2] = uint32(std::stoi(s_v)); - s_v = line.substr(48,8); - ids[3] = uint32(std::stoi(s_v)); - s_v = line.substr(56,8); - ids[4] = uint32(std::stoi(s_v)); - s_v = line.substr(64,8); - ids[5] = uint32(std::stoi(s_v)); - - std::getline (file, line); - s_v = line.substr(8,8); - ids[6] = uint32(std::stoi(s_v)); - s_v = line.substr(16,8); - ids[7] = uint32(std::stoi(s_v)); - - for (uint32& id : ids) - id = old_new_ids_map[id]; - - this->add_hexa(*position, ids[0], ids[1], ids[2], ids[3], ids[4], ids[5],ids[6], ids[7], true); - } else { - if (s_v.compare(0, 6,"CTETRA") == 0) + if (s_v.compare(0, 5,"CHEXA") == 0) { - this->nb_volumes_++; - std::array ids; + this->set_nb_volumes(this->get_nb_volumes() + 1u); + std::array ids; s_v = line.substr(24,8); ids[0] = uint32(std::stoi(s_v)); @@ -165,15 +138,45 @@ class NastranVolumeImport : public NastranIO, public VolumeImportadd_tetra(*position, ids[0], ids[1], ids[2], ids[3], true); + this->add_hexa(*position, ids[0], ids[1], ids[2], ids[3], ids[4], ids[5],ids[6], ids[7], true); } else { - if (s_v.compare(0, 7,"ENDDATA") == 0) - break; - cgogn_log_warning("NastranVolumeImport") << "Elements of type \"" << s_v << "\" are not supported. Ignoring."; + if (s_v.compare(0, 6,"CTETRA") == 0) + { + this->set_nb_volumes(this->get_nb_volumes() + 1u); + std::array ids; + + s_v = line.substr(24,8); + ids[0] = uint32(std::stoi(s_v)); + s_v = line.substr(32,8); + ids[1] = uint32(std::stoi(s_v)); + s_v = line.substr(40,8); + ids[2] = uint32(std::stoi(s_v)); + s_v = line.substr(48,8); + ids[3] = uint32(std::stoi(s_v)); + + for (uint32& id : ids) + id = old_new_ids_map[id]; + + this->add_tetra(*position, ids[0], ids[1], ids[2], ids[3], true); + } else { + if (s_v.compare(0, 7,"ENDDATA") == 0) + break; + cgogn_log_warning("NastranVolumeImport") << "Elements of type \"" << s_v << "\" are not supported. Ignoring."; + } } } @@ -186,7 +189,131 @@ class NastranVolumeImport : public NastranIO, public VolumeImport +class NastranVolumeExport : public VolumeExport +{ +public: + using Inherit = VolumeExport; + using Self = NastranVolumeExport; + using Map = typename Inherit::Map; + using Vertex = typename Inherit::Vertex; + using Volume = typename Inherit::Volume; + using ChunkArrayGen = typename Inherit::ChunkArrayGen; + + +protected: + virtual void export_file_impl(const Map& map, std::ofstream& output, const ExportOptions& option) override + { + + ChunkArrayGen const* pos = this->get_position_attribute(); + const std::string endianness = cgogn::internal::cgogn_is_little_endian ? "LittleEndian" : "BigEndian"; + const std::string format = (option.binary_?"binary" :"ascii"); + std::string scalar_type = pos->get_nested_type_name(); + scalar_type[0] = std::toupper(scalar_type[0]); + + + output << "$$ ---------------------------------------------------------------------------- $"<< std::endl; + output << "$$ NASTRAN MEsh File Generated by CGoGN_2 (ICube/IGG) $"<< std::endl; + output << "$$ ---------------------------------------------------------------------------- $"<< std::endl; + output << "CEND" << std::endl; + output << "BEGIN BULK" << std::endl; + output << "$$ ---------------------------------------------------------------------------- $"<< std::endl; + output << "$$ Vertices position $"<< std::endl; + output << "$$ ---------------------------------------------------------------------------- $"<< std::endl; + + // 1. vertices + uint32 count{1u}; + map.foreach_cell([&](Vertex v) + { + output << "GRID "; + output << std::right; + output.width(8); + output << count++; + output << " "; + output << std::left; + std::stringstream position_stream; + pos->export_element(map.get_embedding(v), position_stream, false); + float32 tmp[3]; + position_stream >> tmp[0]; + position_stream >> tmp[1]; + position_stream >> tmp[2]; + output << std::setw(8) << trunc_float_to8(tmp[0]) << std::setw(8) << trunc_float_to8(tmp[1]) <get_vertices_of_volumes().begin(); + const auto& nb_vert_vol = this->get_number_of_vertices(); + const uint32 nb_vols = nb_vert_vol.size(); + output << std::right; + + + if (this->get_nb_hexas() > 0u) + { + output << "$$ ---------------------------------------------------------------------------- $"<< std::endl; + output << "$$ Hexa indices $"<< std::endl; + output << "$$ ---------------------------------------------------------------------------- $"<< std::endl; + + for (uint32 w = 0u; w < nb_vols; ++w) + { + if (nb_vert_vol[w] == 8u) + { + output << "CHEXA "; + output << std::setw(8) << count++ << std::setw(8)<< 0; + output << std::setw(8) << (*vertices_it++ + 1u) << std::setw(8) << (*vertices_it++ + 1u) << std::setw(8) << (*vertices_it++ + 1u); + output << std::setw(8) << (*vertices_it++ + 1u) << std::setw(8) << (*vertices_it++ + 1u) << std::setw(8) << (*vertices_it++ + 1u) << "+"<< std::endl; + output << "+ " << std::setw(8) << (*vertices_it++ + 1u) << std::setw(8) << (*vertices_it++ + 1u) << std::endl; + } else + { + for (uint32 i = 0u ; i < nb_vert_vol[w] ; ++i) + ++vertices_it; + } + } + } + + if (this->get_nb_tetras() > 0u) + { + vertices_it = this->get_vertices_of_volumes().begin(); + output << "$$ ---------------------------------------------------------------------------- $"<< std::endl; + output << "$$ Tetra indices $"<< std::endl; + output << "$$ ---------------------------------------------------------------------------- $"<< std::endl; + + for (uint32 w = 0u; w < nb_vols; ++w) + { + if (nb_vert_vol[w] == 4u) + { + output << "CTETRA "; + output << std::setw(8) << count++ << std::setw(8)<< 0; + output << std::setw(8) << (*vertices_it++ + 1u) << std::setw(8) << (*vertices_it++ + 1u) << std::setw(8) << (*vertices_it++ + 1u) << std::setw(8) << (*vertices_it++ + 1u) << std::endl; + } else + { + for (uint32 i = 0u ; i < nb_vert_vol[w] ; ++i) + ++vertices_it; + } + } + } + output << "ENDDATA" << std::endl; + } + +private: + static inline std::string trunc_float_to8(float32 f) + { + std::stringstream ss; + ss << f; + std::string res = ss.str(); + size_t expo = res.find('e'); + if (expo != std::string::npos) + { + if ( res[expo+2] == '0') + return res.substr(0,6) + res[expo+1] + res[expo+3]; + + return res.substr(0,5) + res.substr(expo+1); + } + return res.substr(0,8); + } +}; + + +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_NASTRAN_IO_CPP_)) extern template class CGOGN_IO_API NastranIO; extern template class CGOGN_IO_API NastranIO; extern template class CGOGN_IO_API NastranIO>>; @@ -196,8 +323,10 @@ extern template class CGOGN_IO_API NastranVolumeImport; extern template class CGOGN_IO_API NastranVolumeImport>>; extern template class CGOGN_IO_API NastranVolumeImport>>; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_NASTRAN_IO_CPP_)) + +extern template class CGOGN_IO_API NastranVolumeExport>; +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_NASTRAN_IO_CPP_)) } // namespace io } // namespace cgogn -#endif // IO_NASTRAN_IO_H_ +#endif // CGOGN_IO_NASTRAN_IO_H_ diff --git a/cgogn/io/obj_io.cpp b/cgogn/io/obj_io.cpp index 41be7782..7aaea683 100644 --- a/cgogn/io/obj_io.cpp +++ b/cgogn/io/obj_io.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_IO_DLL_EXPORT -#define IO_OBJ_IO_CPP_ +#define CGOGN_IO_OBJ_IO_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/io/obj_io.h b/cgogn/io/obj_io.h index 437c248e..3cc6b9cb 100644 --- a/cgogn/io/obj_io.h +++ b/cgogn/io/obj_io.h @@ -21,14 +21,14 @@ * * *******************************************************************************/ -#ifndef IO_OBJ_IO_H_ -#define IO_OBJ_IO_H_ +#ifndef CGOGN_IO_OBJ_IO_H_ +#define CGOGN_IO_OBJ_IO_H_ -#include -#include -#include +#include +#include +#include -#include +#include namespace cgogn { @@ -151,14 +151,14 @@ class ObjSurfaceImport : public SurfaceImport { } }; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_OBJ_IO_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_OBJ_IO_CPP_)) extern template class CGOGN_IO_API ObjSurfaceImport; extern template class CGOGN_IO_API ObjSurfaceImport; extern template class CGOGN_IO_API ObjSurfaceImport>>; extern template class CGOGN_IO_API ObjSurfaceImport>>; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_OBJ_IO_H_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_OBJ_IO_CPP_)) } // namespace io } // namespace cgogn -#endif // IO_OBJ_IO_H_ +#endif // CGOGN_IO_OBJ_IO_H_ diff --git a/cgogn/io/off_io.cpp b/cgogn/io/off_io.cpp index caf7af0b..80b4a941 100644 --- a/cgogn/io/off_io.cpp +++ b/cgogn/io/off_io.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_IO_DLL_EXPORT -#define IO_OFF_IO_CPP_ +#define CGOGN_IO_OFF_IO_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/io/off_io.h b/cgogn/io/off_io.h index ca739525..301f8b5d 100644 --- a/cgogn/io/off_io.h +++ b/cgogn/io/off_io.h @@ -21,14 +21,14 @@ * * *******************************************************************************/ -#ifndef IO_OFF_IO_H_ -#define IO_OFF_IO_H_ +#ifndef CGOGN_IO_OFF_IO_H_ +#define CGOGN_IO_OFF_IO_H_ -#include -#include -#include +#include +#include +#include -#include +#include namespace cgogn { @@ -242,14 +242,14 @@ class OffSurfaceImport : public SurfaceImport { } }; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_OFF_IO_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_OFF_IO_CPP_)) extern template class CGOGN_IO_API OffSurfaceImport; extern template class CGOGN_IO_API OffSurfaceImport; extern template class CGOGN_IO_API OffSurfaceImport>>; extern template class CGOGN_IO_API OffSurfaceImport>>; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_OFF_IO_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_OFF_IO_CPP_)) } // namespace io } // namespace cgogn -#endif // IO_OFF_IO_H_ +#endif // CGOGN_IO_OFF_IO_H_ diff --git a/cgogn/io/ply_io.cpp b/cgogn/io/ply_io.cpp index 5c3c55f4..f7104843 100644 --- a/cgogn/io/ply_io.cpp +++ b/cgogn/io/ply_io.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_IO_DLL_EXPORT -#define IO_PLY_IO_CPP_ +#define CGOGN_IO_PLY_IO_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/io/ply_io.h b/cgogn/io/ply_io.h index 96fc41a1..3ed9f480 100644 --- a/cgogn/io/ply_io.h +++ b/cgogn/io/ply_io.h @@ -21,15 +21,15 @@ * * *******************************************************************************/ -#ifndef IO_PLY_IO_H_ -#define IO_PLY_IO_H_ +#ifndef CGOGN_IO_PLY_IO_H_ +#define CGOGN_IO_PLY_IO_H_ -#include -#include -#include +#include +#include +#include -#include -#include +#include +#include namespace cgogn { @@ -115,13 +115,13 @@ class PlySurfaceImport : public SurfaceImport { } }; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_PLY_IO_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_PLY_IO_CPP_)) extern template class CGOGN_IO_API PlySurfaceImport; extern template class CGOGN_IO_API PlySurfaceImport; extern template class CGOGN_IO_API PlySurfaceImport>>; extern template class CGOGN_IO_API PlySurfaceImport>>; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_PLY_IO_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_PLY_IO_CPP_)) }// namespace io } // namespace cgogn -#endif // IO_PLY_IO_H_ +#endif // CGOGN_IO_PLY_IO_H_ diff --git a/cgogn/io/surface_import.cpp b/cgogn/io/surface_import.cpp index b3f3064c..a2466b8e 100644 --- a/cgogn/io/surface_import.cpp +++ b/cgogn/io/surface_import.cpp @@ -21,9 +21,9 @@ * * *******************************************************************************/ #define CGOGN_IO_DLL_EXPORT -#define IO_SURFACE_IMPORT_CPP_ +#define CGOGN_IO_SURFACE_IMPORT_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index 139951c0..4c0fc922 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -21,22 +21,22 @@ * * *******************************************************************************/ -#ifndef IO_SURFACE_IMPORT_H_ -#define IO_SURFACE_IMPORT_H_ +#ifndef CGOGN_IO_SURFACE_IMPORT_H_ +#define CGOGN_IO_SURFACE_IMPORT_H_ #include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include -#include -#include -#include +#include +#include +#include namespace cgogn { @@ -59,7 +59,7 @@ class SurfaceImport : public MeshImportGen using ChunkArray = cgogn::ChunkArray; using ChunkArrayContainer = cgogn::ChunkArrayContainer; template - using AttributeHandler = AttributeHandler; + using Attribute = Attribute; protected: @@ -116,7 +116,7 @@ class SurfaceImport : public MeshImportGen mbuild.template create_embedding(); mbuild.template swap_chunk_array_container(this->vertex_attributes_); - typename Map::template VertexAttributeHandler> darts_per_vertex = + typename Map::template VertexAttribute> darts_per_vertex = map.template add_attribute, Vertex::ORBIT>("darts_per_vertex"); uint32 faces_vertex_index = 0; @@ -196,10 +196,16 @@ class SurfaceImport : public MeshImportGen }); if (nb_boundary_edges > 0) + { mbuild.close_map(); + cgogn_log_info("create_map") << nb_boundary_edges << " hole(s) have been closed"; + } if (need_vertex_unicity_check) + { map.template enforce_unique_orbit_embedding(); + cgogn_log_warning("create_map") << "Import Surface: non manifold vertices detected and corrected"; + } if (this->face_attributes_.get_nb_attributes() > 0) { @@ -212,12 +218,12 @@ class SurfaceImport : public MeshImportGen } }; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_SURFACE_IMPORT_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_SURFACE_IMPORT_CPP_)) extern template class CGOGN_IO_API SurfaceImport; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_SURFACE_IMPORT_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_SURFACE_IMPORT_CPP_)) } // namespace io } // namespace cgogn -#endif // IO_SURFACE_IMPORT_H_ +#endif // CGOGN_IO_SURFACE_IMPORT_H_ diff --git a/cgogn/io/tet_io.cpp b/cgogn/io/tet_io.cpp index 80b280d2..3da34ca8 100644 --- a/cgogn/io/tet_io.cpp +++ b/cgogn/io/tet_io.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_IO_DLL_EXPORT -#define IO_TET_IO_CPP_ +#define CGOGN_IO_TET_IO_CPP_ -#include +#include namespace cgogn { @@ -36,5 +36,7 @@ template class CGOGN_IO_API TetVolumeImport; template class CGOGN_IO_API TetVolumeImport>>; template class CGOGN_IO_API TetVolumeImport>>; +template class CGOGN_IO_API TetVolumeExport>; + } // namespace io } // namespace cgogn diff --git a/cgogn/io/tet_io.h b/cgogn/io/tet_io.h index d430f062..194a0c9f 100644 --- a/cgogn/io/tet_io.h +++ b/cgogn/io/tet_io.h @@ -21,14 +21,15 @@ * * *******************************************************************************/ -#ifndef IO_TET_IO_H_ -#define IO_TET_IO_H_ +#ifndef CGOGN_IO_TET_IO_H_ +#define CGOGN_IO_TET_IO_H_ #include -#include -#include -#include +#include +#include +#include +#include namespace cgogn { @@ -47,7 +48,7 @@ class TetVolumeImport : public VolumeImport protected: virtual bool import_file_impl(const std::string& filename) override { - ChunkArray* position = this->vertex_attributes_.template add_attribute("position"); + ChunkArray* position = this->template get_position_attribute(); std::ifstream fp(filename, std::ios::in); std::string line; @@ -57,27 +58,29 @@ class TetVolumeImport : public VolumeImport { std::getline(fp, line); std::istringstream iss(line); - iss >> this->nb_vertices_; + uint32 nbv = 0u; + iss >> nbv; + this->set_nb_vertices(nbv); } // reading number of tetrahedra { std::getline(fp, line); std::istringstream iss(line); - iss >> this->nb_volumes_; - this->volumes_types.reserve(this->nb_volumes_); - this->volumes_vertex_indices_.reserve(4u*this->nb_volumes_); + uint32 nbw = 0u; + iss >> nbw; + this->set_nb_volumes(nbw); } //reading vertices - for(uint32 i = 0u; i < this->nb_vertices_; ++i) + for(uint32 i = 0u, end = this->get_nb_vertices(); i < end; ++i) { do { std::getline(fp, line); } while (line.empty()); - const uint32 new_id = this->vertex_attributes_.template insert_lines<1>(); + const uint32 new_id = this->insert_line_vertex_container(); auto& v = position->operator [](new_id); std::istringstream iss(line); iss >> v[0]; @@ -88,7 +91,7 @@ class TetVolumeImport : public VolumeImport // reading volumes - for (uint32 i = 0u; i < this->nb_volumes_ ; ++i) + for (uint32 i = 0u, end = this->get_nb_volumes(); i < end; ++i) { do { @@ -104,10 +107,10 @@ class TetVolumeImport : public VolumeImport iss.clear(); char connector; - iss >> connector >> connector; + iss >> connector >> connector; // the line should be like this: # C id0 id1 id2 id3 if (connector == 'C') { - --this->nb_volumes_; + this->set_nb_volumes(this->get_nb_volumes() -1u); std::array ids; iss >> ids[0] >> ids[1] >> ids[2] >> ids[3]; this->add_connector(ids[0], ids[1], ids[2], ids[3]); @@ -135,14 +138,65 @@ class TetVolumeImport : public VolumeImport } }; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_TET_IO_CPP_)) + +template +class TetVolumeExport : public VolumeExport +{ +public: + using Inherit = VolumeExport; + using Self = TetVolumeExport; + using Map = typename Inherit::Map; + using Vertex = typename Inherit::Vertex; + using Volume = typename Inherit::Volume; + using ChunkArrayGen = typename Inherit::ChunkArrayGen; + + +protected: + virtual void export_file_impl(const Map& map, std::ofstream& output, const ExportOptions& option) override + { + + ChunkArrayGen const* pos = this->get_position_attribute(); + const std::string endianness = cgogn::internal::cgogn_is_little_endian ? "LittleEndian" : "BigEndian"; + const std::string format = (option.binary_?"binary" :"ascii"); + std::string scalar_type = pos->get_nested_type_name(); + scalar_type[0] = std::toupper(scalar_type[0]); + const auto& nb_vert_vol = this->get_number_of_vertices(); + const uint32 nb_vols = nb_vert_vol.size(); + + // 1. vertices + output << map.template nb_cells() << " vertices" << std::endl; + output << nb_vols << " cells" << std::endl; + + map.foreach_cell([&](Vertex v) + { + pos->export_element(map.get_embedding(v), output, false); + output << std::endl; + }); + + auto vertices_it = this->get_vertices_of_volumes().begin(); + for (uint32 w = 0u; w < nb_vols; ++w) + { + output << nb_vert_vol[w] << " "; + for (uint32 i = 0u ; i < nb_vert_vol[w]; ++i) + { + output << *vertices_it << " "; + ++vertices_it; + } + output << std::endl; + } + } +}; + +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_TET_IO_CPP_)) extern template class CGOGN_IO_API TetVolumeImport; extern template class CGOGN_IO_API TetVolumeImport; extern template class CGOGN_IO_API TetVolumeImport>>; extern template class CGOGN_IO_API TetVolumeImport>>; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_TET_IO_CPP_)) + +extern template class CGOGN_IO_API TetVolumeExport>; +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_TET_IO_CPP_)) } // namespace io } // namespace cgogn -#endif // IO_TET_IO_H_ +#endif // CGOGN_IO_TET_IO_H_ diff --git a/cgogn/io/tetgen_io.cpp b/cgogn/io/tetgen_io.cpp index 5a827f82..d12d2420 100644 --- a/cgogn/io/tetgen_io.cpp +++ b/cgogn/io/tetgen_io.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_IO_DLL_EXPORT -#define IO_TETGEN_IO_CPP_ +#define CGOGN_IO_TETGEN_IO_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/io/tetgen_io.h b/cgogn/io/tetgen_io.h index 54e36a54..d6952246 100644 --- a/cgogn/io/tetgen_io.h +++ b/cgogn/io/tetgen_io.h @@ -21,16 +21,16 @@ * * *******************************************************************************/ -#ifndef IO_TETGEN_IO_H_ -#define IO_TETGEN_IO_H_ +#ifndef CGOGN_IO_TETGEN_IO_H_ +#define CGOGN_IO_TETGEN_IO_H_ #include #include -#include -#include -#include -#include +#include +#include +#include +#include namespace cgogn { @@ -53,8 +53,7 @@ class TetgenVolumeImport : public VolumeImport const std::string node_filename = filename.substr(0, filename.rfind('.')) + ".node"; const std::string ele_filename = filename.substr(0, filename.rfind('.')) + ".ele"; - ChunkArray* position = this->vertex_attributes_.template add_attribute("position"); - + ChunkArray* position = this->template get_position_attribute(); std::ifstream node_file(node_filename, std::ios::in); if (!node_file.good()) { @@ -81,7 +80,9 @@ class TetgenVolumeImport : public VolumeImport }while(line.empty()); std::istringstream iss(line); - iss >> this->nb_vertices_; + uint32 nbv = 0u; + iss >> nbv; + this->set_nb_vertices(nbv); } //Reading number of tetrahedra in ELE file @@ -92,15 +93,15 @@ class TetgenVolumeImport : public VolumeImport }while(line.empty()); std::istringstream iss(line); - iss >> this->nb_volumes_; - this->volumes_types.reserve(this->nb_volumes_); - this->volumes_vertex_indices_.reserve(this->nb_volumes_); + uint32 nbw = 0u; + iss >> nbw; + this->set_nb_volumes(nbw); } //Reading vertices std::map old_new_ids_map; - for(uint32 i = 0u ; i < this->nb_vertices_ ; ++i) + for(uint32 i = 0u, end = this->get_nb_vertices() ; i < end; ++i) { do { @@ -112,7 +113,7 @@ class TetgenVolumeImport : public VolumeImport uint32 old_index; iss >> old_index; - const uint32 new_index = this->vertex_attributes_.template insert_lines<1>(); + const uint32 new_index = this->insert_line_vertex_container(); old_new_ids_map[old_index] = new_index; auto& v = position->operator [](new_index); @@ -122,7 +123,7 @@ class TetgenVolumeImport : public VolumeImport } // reading tetrahedra - for(uint32 i = 0u; i < this->nb_volumes_; ++i) + for(uint32 i = 0u, end = this->get_nb_volumes(); i < end; ++i) { do { @@ -145,13 +146,13 @@ class TetgenVolumeImport : public VolumeImport } }; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_TETGEN_IO_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_TETGEN_IO_CPP_)) extern template class CGOGN_IO_API TetgenVolumeImport; extern template class CGOGN_IO_API TetgenVolumeImport; extern template class CGOGN_IO_API TetgenVolumeImport>>; extern template class CGOGN_IO_API TetgenVolumeImport>>; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_TETGEN_IO_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_TETGEN_IO_CPP_)) } // namespace io } // namespace cgogn -#endif // IO_TETGEN_IO_H_ +#endif // CGOGN_IO_TETGEN_IO_H_ diff --git a/cgogn/io/volume_export.h b/cgogn/io/volume_export.h new file mode 100644 index 00000000..3caae81e --- /dev/null +++ b/cgogn/io/volume_export.h @@ -0,0 +1,282 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef CGOGN_IO_VOLUME_EXPORT_H_ +#define CGOGN_IO_VOLUME_EXPORT_H_ + +#include + +#include +#include +#include + +#include +#include + +namespace cgogn +{ + +namespace io +{ + +struct ExportOptions +{ + inline ExportOptions(const std::string& filename, std::vector> const& attributes, bool binary) : + filename_(filename) + ,binary_(binary) + ,attributes_to_export_(attributes) + {} + + std::string filename_; + bool binary_; + std::vector> attributes_to_export_; +}; + +template +class VolumeExport +{ +public: + using Self = VolumeExport; + using Map = MAP; + using Vertex = typename Map::Vertex; + using Volume = typename Map::Volume; + using ChunkArrayGen = typename Map::ChunkArrayGen; + using ChunkArrayContainer = typename Map::template ChunkArrayContainer; + + inline VolumeExport() : + vertices_of_volumes_() + ,number_of_vertices_() + ,nb_tetras_(0u) + ,nb_pyramids_(0u) + ,nb_triangular_prisms_(0u) + ,nb_hexas_(0u) + ,vertex_attributes() + ,volume_attributes() + ,position_attribute(nullptr) + {} + + virtual ~VolumeExport() {} + + void export_file(Map& map, const ExportOptions& options) + { + Scoped_C_Locale loc; + this->reset(); + const ChunkArrayContainer& ver_cac= map.template get_const_attribute_container(); + const ChunkArrayContainer& vol_cac= map.template get_const_attribute_container(); + + for (const auto& pair : options.attributes_to_export_) + { + if (pair.first == Vertex::ORBIT) + { + ChunkArrayGen* ver_cag = ver_cac.get_attribute(pair.second); + if (pair.second == "position") + position_attribute = ver_cag; + else { + if (ver_cag) + vertex_attributes.push_back(ver_cag); + } + } else { + ChunkArrayGen* vol_cag = vol_cac.get_attribute(pair.second); + if (vol_cag) + volume_attributes.push_back(vol_cag); + } + } + + if (position_attribute == nullptr) + { + cgogn_log_warning("VolumeExport::export_file") << "The position attribute is invalid."; + return; + } + + auto output = io::create_file(options.filename_); + if (!output || !output->good()) + return; + indices_ = map.template add_attribute("indices_vert"); + this->prepare_for_export(map); + this->export_file_impl(map,*output, options); + map.remove_attribute(indices_); + } + + protected: + + virtual void export_file_impl(const Map& map, std::ofstream& output, const ExportOptions& options) = 0; + + inline uint32 get_nb_tetras() const + { + return nb_tetras_; + } + + inline uint32 get_nb_pyramids() const + { + return nb_pyramids_; + } + + inline uint32 get_nb_triangular_prisms() const + { + return nb_triangular_prisms_; + } + + inline uint32 get_nb_hexas() const + { + return nb_hexas_; + } + + inline std::vector const & get_vertices_of_volumes() const + { + return vertices_of_volumes_; + } + + inline std::vector const & get_number_of_vertices() const + { + return number_of_vertices_; + } + + inline std::vector const & get_vertex_attributes() const + { + return vertex_attributes; + } + + inline std::vector const & get_volume_attributes() const + { + return volume_attributes; + } + + ChunkArrayGen const * get_position_attribute() const + { + return position_attribute; + } +private: + void prepare_for_export(Map& map) + { + number_of_vertices_.reserve(map.template nb_cells()); + vertices_of_volumes_.reserve(4u* number_of_vertices_.capacity()); + + uint32 count{0u}; + map.foreach_cell([&](Vertex v) { indices_[v] = count++;} ); + + map.foreach_cell([&](Volume w) + { + uint32 nb_vert{0u}; + map.foreach_incident_vertex(w, [&nb_vert](Vertex) {++nb_vert;}); + Dart it = w.dart; + + if (nb_vert == 4u) + { + number_of_vertices_.push_back(4u); + ++nb_tetras_; + vertices_of_volumes_.push_back(indices_[Vertex(it)]); + it = map.phi1(it); + vertices_of_volumes_.push_back(indices_[Vertex(it)]); + it = map.phi1(it); + vertices_of_volumes_.push_back(indices_[Vertex(it)]); + it = map.template phi<211>(it); + vertices_of_volumes_.push_back(indices_[Vertex(it)]); + } else { + if (nb_vert == 5u) + { + number_of_vertices_.push_back(5u); + ++nb_pyramids_; + vertices_of_volumes_.push_back(indices_[Vertex(it)]); + it = map.phi1(it); + vertices_of_volumes_.push_back(indices_[Vertex(it)]); + it = map.phi1(it); + vertices_of_volumes_.push_back(indices_[Vertex(it)]); + it = map.phi1(it); + vertices_of_volumes_.push_back(indices_[Vertex(it)]); + it = map.template phi<212>(it); + vertices_of_volumes_.push_back(indices_[Vertex(it)]); + } else { + if (nb_vert == 6u) + { + number_of_vertices_.push_back(6u); + ++nb_triangular_prisms_; + vertices_of_volumes_.push_back(indices_[Vertex(it)]); + it = map.phi1(it); + vertices_of_volumes_.push_back(indices_[Vertex(it)]); + it = map.phi1(it); + vertices_of_volumes_.push_back(indices_[Vertex(it)]); + it = map.template phi<21121>(w.dart); + vertices_of_volumes_.push_back(indices_[Vertex(it)]); + it = map.phi_1(it); + vertices_of_volumes_.push_back(indices_[Vertex(it)]); + it = map.phi_1(it); + vertices_of_volumes_.push_back(indices_[Vertex(it)]); + } else { + if (nb_vert == 8u) + { + number_of_vertices_.push_back(8u); + ++nb_hexas_; + vertices_of_volumes_.push_back(indices_[Vertex(it)]); + it = map.phi_1(it); + vertices_of_volumes_.push_back(indices_[Vertex(it)]); + it = map.phi_1(it); + vertices_of_volumes_.push_back(indices_[Vertex(it)]); + it = map.phi_1(it); + vertices_of_volumes_.push_back(indices_[Vertex(it)]); + it = map.template phi<21121>(w.dart); + vertices_of_volumes_.push_back(indices_[Vertex(it)]); + it = map.phi1(it); + vertices_of_volumes_.push_back(indices_[Vertex(it)]); + it = map.phi1(it); + vertices_of_volumes_.push_back(indices_[Vertex(it)]); + it = map.phi1(it); + vertices_of_volumes_.push_back(indices_[Vertex(it)]); + } else { + cgogn_log_warning("VolumeExport::prepare_for_export") << "Unknown volume with " << nb_vert << " vertices. Ignoring."; + } + } + } + } + }); + } + + void reset() + { + vertices_of_volumes_.clear(); + number_of_vertices_.clear(); + nb_tetras_ = 0u; + nb_pyramids_ = 0u; + nb_triangular_prisms_ = 0u; + nb_hexas_ = 0u; + vertex_attributes.clear(); + volume_attributes.clear(); + position_attribute = nullptr; + } + + std::vector vertices_of_volumes_; + std::vector number_of_vertices_; + typename Map::template Attribute indices_; + uint32 nb_tetras_; + uint32 nb_pyramids_; + uint32 nb_triangular_prisms_; + uint32 nb_hexas_; + std::vector vertex_attributes; + std::vector volume_attributes; + ChunkArrayGen* position_attribute; +}; + +} // namespace io + +} // namespace cgogn + +#endif // CGOGN_IO_VOLUME_EXPORT_H_ diff --git a/cgogn/io/volume_import.cpp b/cgogn/io/volume_import.cpp index bd55814f..1ad0e9f5 100644 --- a/cgogn/io/volume_import.cpp +++ b/cgogn/io/volume_import.cpp @@ -21,9 +21,9 @@ * * *******************************************************************************/ #define CGOGN_IO_DLL_EXPORT -#define IO_VOLUME_IMPORT_CPP_ +#define CGOGN_IO_VOLUME_IMPORT_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/io/volume_import.h b/cgogn/io/volume_import.h index d1f45ac8..673fc0dc 100644 --- a/cgogn/io/volume_import.h +++ b/cgogn/io/volume_import.h @@ -21,20 +21,21 @@ * * *******************************************************************************/ -#ifndef IO_VOLUME_IMPORT_H_ -#define IO_VOLUME_IMPORT_H_ +#ifndef CGOGN_IO_VOLUME_IMPORT_H_ +#define CGOGN_IO_VOLUME_IMPORT_H_ #include -#include -#include -#include +#include +#include +#include -#include +#include -#include -#include -#include +#include +#include +#include +#include #include @@ -112,15 +113,6 @@ template class VolumeImport : public MeshImportGen { public: - enum VolumeType - { - Tetra, - Pyramid, - TriangularPrism, - Hexa, - Connector - }; - using Self = VolumeImport; using Inherit = MeshImportGen; using Map = CMap3; @@ -136,12 +128,13 @@ class VolumeImport : public MeshImportGen using ChunkArrayContainer = cgogn::ChunkArrayContainer; template - using AttributeHandler = AttributeHandler; + using Attribute = Attribute; using MapBuilder = cgogn::CMap3Builder_T; virtual ~VolumeImport() override {} -protected: +private: + uint32 nb_vertices_; uint32 nb_volumes_; @@ -151,7 +144,57 @@ class VolumeImport : public MeshImportGen ChunkArrayContainer vertex_attributes_; ChunkArrayContainer volume_attributes_; +protected: + + inline void set_nb_vertices(uint32 nbv) + { + nb_vertices_ = nbv; + } + + inline uint32 get_nb_vertices() const + { + return nb_vertices_; + } + + inline void set_nb_volumes(uint32 nbw) + { + nb_volumes_ = nbw; + volumes_types.reserve(nbw); + volumes_vertex_indices_.reserve(8u * nbw); + } + + inline uint32 get_nb_volumes() const + { + return nb_volumes_; + } + + template + inline ChunkArray* get_position_attribute() + { + auto res = this->vertex_attributes_.template add_attribute("position"); + if (res != nullptr) + return res; + else + return this->vertex_attributes_.template get_attribute("position"); + } + + inline uint32 insert_line_vertex_container() + { + return vertex_attributes_.template insert_lines<1>(); + } + + inline ChunkArrayContainer& get_vertex_attributes_container() + { + return vertex_attributes_; + } + + inline ChunkArrayContainer& get_volume_attributes_container() + { + return volume_attributes_; + } + public: + VolumeImport() : nb_vertices_(0u) ,volumes_types() @@ -171,18 +214,18 @@ class VolumeImport : public MeshImportGen mbuild.template create_embedding(); mbuild.template swap_chunk_array_container(this->vertex_attributes_); - typename Map::template VertexAttributeHandler> darts_per_vertex = map.template add_attribute, Vertex::ORBIT>("darts_per_vertex"); + typename Map::template VertexAttribute> darts_per_vertex = map.template add_attribute, Vertex::ORBIT>("darts_per_vertex"); uint32 index = 0u; typename Map::DartMarkerStore m(map); //for each volume of table - for(uint32 i = 0u; i < this->nb_volumes_; ++i) + for (uint32 i = 0u; i < this->nb_volumes_; ++i) { // store volume in buffer, removing degenated faces const VolumeType vol_type = this->volumes_types[i]; - if(vol_type == VolumeType::Tetra) //tetrahedral case + if (vol_type == VolumeType::Tetra) //tetrahedral case { const Dart d = mbuild.add_pyramid_topo(3u); @@ -195,7 +238,7 @@ class VolumeImport : public MeshImportGen for (const Dart dv : vertices_of_tetra) { const uint32 emb = this->volumes_vertex_indices_[index++]; - mbuild.init_parent_vertex_embedding(dv,emb); + mbuild.init_parent_vertex_embedding(dv, emb); Dart dd = dv; do @@ -206,7 +249,7 @@ class VolumeImport : public MeshImportGen } while(dd != dv); } } - else if(vol_type == VolumeType::Pyramid) //pyramidal case + else if (vol_type == VolumeType::Pyramid) //pyramidal case { Dart d = mbuild.add_pyramid_topo(4u); @@ -220,7 +263,7 @@ class VolumeImport : public MeshImportGen for (Dart dv : vertices_of_pyramid) { const uint32 emb = this->volumes_vertex_indices_[index++]; - mbuild.init_parent_vertex_embedding(dv,emb); + mbuild.init_parent_vertex_embedding(dv, emb); Dart dd = dv; do @@ -231,7 +274,7 @@ class VolumeImport : public MeshImportGen } while(dd != dv); } } - else if(vol_type == VolumeType::TriangularPrism) //prism case + else if (vol_type == VolumeType::TriangularPrism) //prism case { Dart d = mbuild.add_prism_topo(3u); const std::array vertices_of_prism = { @@ -240,13 +283,13 @@ class VolumeImport : public MeshImportGen map.phi_1(d), map.phi2(map.phi1(map.phi1(map.phi2(map.phi_1(d))))), map.phi2(map.phi1(map.phi1(map.phi2(d)))), - map.phi2(map.phi1(map.phi1(map.phi2(map.phi1(d))))), + map.phi2(map.phi1(map.phi1(map.phi2(map.phi1(d))))) }; for (Dart dv : vertices_of_prism) { const uint32 emb = this->volumes_vertex_indices_[index++]; - mbuild.init_parent_vertex_embedding(dv,emb); + mbuild.init_parent_vertex_embedding(dv, emb); Dart dd = dv; do @@ -257,7 +300,7 @@ class VolumeImport : public MeshImportGen } while(dd != dv); } } - else if(vol_type == VolumeType::Hexa) //hexahedral case + else if (vol_type == VolumeType::Hexa) //hexahedral case { Dart d = mbuild.add_prism_topo(4u); const std::array vertices_of_hexa = { @@ -275,7 +318,7 @@ class VolumeImport : public MeshImportGen for (Dart dv : vertices_of_hexa) { const uint32 emb = this->volumes_vertex_indices_[index++]; - mbuild.init_parent_vertex_embedding(dv,emb); + mbuild.init_parent_vertex_embedding(dv, emb); Dart dd = dv; do @@ -285,30 +328,19 @@ class VolumeImport : public MeshImportGen dd = map.phi1(map.phi2(dd)); } while(dd != dv); } - } else { //end of hexa - + } + else + { //end of hexa if (vol_type == VolumeType::Connector) { - index+=4u; + index += 4u; // The second part of the code generates connectors automatically. We don't have to do anything here. } } } - // utilitary function - auto sew_volumes = [&mbuild,&map,&m](Dart w1, Dart w2) - { - const Dart w1_begin = w1; - do { - mbuild.phi3_sew(w1, w2); - w1 = map.phi1(w1); - w2 = map.phi_1(w2); - } while (w1_begin != w1); - }; - - //reconstruct neighbourhood - uint32 nbBoundaryFaces = 0u; + uint32 nb_boundary_faces = 0u; map.foreach_dart([&] (Dart d) { if (m.is_marked(d)) @@ -321,9 +353,9 @@ class VolumeImport : public MeshImportGen do { const std::vector& vec = darts_per_vertex[Vertex(map.phi1(d_it))]; - for(auto it = vec.begin(); it != vec.end() && good_dart.is_nil(); ++it) + for (auto it = vec.begin(); it != vec.end() && good_dart.is_nil(); ++it) { - if(map.get_embedding(Vertex(map.phi1(*it))) == map.get_embedding(Vertex(d_it)) && + if (map.get_embedding(Vertex(map.phi1(*it))) == map.get_embedding(Vertex(d_it)) && map.get_embedding(Vertex(map.phi_1(*it))) == map.get_embedding(Vertex(map.phi1(map.phi1(d_it))))) { good_dart = *it; @@ -339,23 +371,23 @@ class VolumeImport : public MeshImportGen const uint32 degD = map.codegree(Face(d)); const uint32 degGD = map.codegree(Face(good_dart)); - if(degD == degGD) // normal case : the two opposite faces have the same degree + if (degD == degGD) // normal case : the two opposite faces have the same degree { - sew_volumes(d, good_dart); + mbuild.sew_volumes(Volume(d), Volume(good_dart)); m.unmark_orbit(Face(d)); } else { // there is one face of degree 4 and one face of degree 3. - if(degD > degGD) // face of d is quad + if (degD > degGD) // face of d is quad { const Dart another_d = map.phi1(map.phi1(d)); const std::vector& vec = darts_per_vertex[Vertex(map.phi_1(d))]; Dart another_good_dart; - for(auto it = vec.begin(); it != vec.end() && another_good_dart.is_nil(); ++it) + for (auto it = vec.begin(); it != vec.end() && another_good_dart.is_nil(); ++it) { - if(map.get_embedding(Vertex(map.phi1(*it))) == map.get_embedding(Vertex(another_d)) && + if (map.get_embedding(Vertex(map.phi1(*it))) == map.get_embedding(Vertex(another_d)) && map.get_embedding(Vertex(map.phi_1(*it))) == map.get_embedding(Vertex(map.phi1(map.phi1(another_d))))) { another_good_dart = *it ; @@ -367,37 +399,40 @@ class VolumeImport : public MeshImportGen { Dart q1_it = d; Dart q2_it = map.phi_1(d_quad); - do { + do + { mbuild.init_parent_vertex_embedding(q2_it, map.get_embedding(Vertex(q1_it))); q1_it = map.phi1(q1_it); q2_it = map.phi_1(q2_it); } while (q1_it != d); } - sew_volumes(d, map.phi1(map.phi1(d_quad))); + mbuild.sew_volumes(Volume(d), Volume(map.phi1(map.phi1(d_quad)))); m.unmark_orbit(Face(d)); - sew_volumes(good_dart, map.phi2(map.phi1(map.phi1(d_quad)))); + mbuild.sew_volumes(Volume(good_dart), Volume(map.phi2(map.phi1(map.phi1(d_quad))))); m.unmark_orbit(Face(good_dart)); - if(!another_good_dart.is_nil()) + if (!another_good_dart.is_nil()) { - sew_volumes(another_good_dart, map.phi2(d_quad)); + mbuild.sew_volumes(Volume(another_good_dart), Volume(map.phi2(d_quad))); m.unmark_orbit(Face(another_good_dart)); - } else + } + else { m.unmark_orbit(Face2(map.phi2(d_quad))); - ++nbBoundaryFaces; + ++nb_boundary_faces; } } - else { // // face of d is tri + else // face of d is tri + { const Dart another_dart = map.phi_1(d); std::vector& vec = darts_per_vertex[Vertex(d)]; Dart another_good_dart; - for(auto it = vec.begin(); it != vec.end() && another_good_dart.is_nil(); ++it) + for (auto it = vec.begin(); it != vec.end() && another_good_dart.is_nil(); ++it) { - if(map.get_embedding(Vertex(map.phi1(*it))) == map.get_embedding(Vertex(another_dart)) && + if (map.get_embedding(Vertex(map.phi1(*it))) == map.get_embedding(Vertex(another_dart)) && map.get_embedding(Vertex(map.phi_1(*it))) == map.get_embedding(Vertex(map.phi1(map.phi1(good_dart))))) { another_good_dart = *it ; @@ -408,27 +443,29 @@ class VolumeImport : public MeshImportGen { Dart q1_it = good_dart; Dart q2_it = d_quad; - do { + do + { mbuild.init_parent_vertex_embedding(q2_it, map.get_embedding(Vertex(q1_it))); q1_it = map.phi1(q1_it); q2_it = map.phi_1(q2_it); } while (q1_it != good_dart); } - sew_volumes(d_quad, map.phi_1(good_dart)); + mbuild.sew_volumes(Volume(d_quad), Volume(map.phi_1(good_dart))); m.unmark_orbit(Face(good_dart)); - - sew_volumes(d, map.phi2(map.phi_1(d_quad))); + mbuild.sew_volumes(Volume(d), Volume(map.phi2(map.phi_1(d_quad)))); m.unmark_orbit(Face(d)); if (!another_good_dart.is_nil()) { - sew_volumes(another_good_dart, map.phi1(map.phi2(map.phi1(d_quad)))); + mbuild.sew_volumes(Volume(another_good_dart), Volume(map.phi1(map.phi2(map.phi1(d_quad))))); m.unmark_orbit(Face(another_good_dart)); - } else { + } + else + { m.unmark_orbit(Face2(map.phi1(map.phi2(map.phi1(d_quad))))); - ++nbBoundaryFaces; + ++nb_boundary_faces; } } } @@ -436,20 +473,19 @@ class VolumeImport : public MeshImportGen else { m.unmark_orbit(Face2(d)); - ++nbBoundaryFaces; + ++nb_boundary_faces; } } }); - - if (nbBoundaryFaces > 0) + if (nb_boundary_faces > 0) { mbuild.close_map(); - cgogn_log_info("create_map") << "Map closed with " << nbBoundaryFaces << " boundary face(s)."; + cgogn_log_info("create_map") << "Map closed with " << nb_boundary_faces << " boundary face(s)."; } uint32 nb_vert_dart_marking = 0u; - map.template foreach_cell([&nb_vert_dart_marking](Vertex v){++nb_vert_dart_marking;}); + map.template foreach_cell([&nb_vert_dart_marking](Vertex){++nb_vert_dart_marking;}); if (this->nb_vertices_ != nb_vert_dart_marking) map.template enforce_unique_orbit_embedding(); @@ -464,9 +500,11 @@ class VolumeImport : public MeshImportGen } protected: + virtual void clear() override { - nb_vertices_ = 0; + set_nb_vertices(0u); + set_nb_volumes(0u); volumes_types.clear(); volumes_vertex_indices_.clear(); vertex_attributes_.remove_attributes(); @@ -488,10 +526,11 @@ class VolumeImport : public MeshImportGen this->volumes_vertex_indices_.push_back(p6); this->volumes_vertex_indices_.push_back(p7); } + template inline void reoriente_hexa(ChunkArrayconst& pos, uint32& p0, uint32& p1, uint32& p2, uint32& p3, uint32& p4, uint32& p5, uint32& p6, uint32& p7) { - if (geometry::test_orientation_3D(pos[p4], pos[p0],pos[p1],pos[p2]) == geometry::Orientation3D::OVER) + if (geometry::test_orientation_3D(pos[p4], pos[p0], pos[p1], pos[p2]) == geometry::Orientation3D::OVER) { std::swap(p0, p3); std::swap(p1, p2); @@ -504,7 +543,7 @@ class VolumeImport : public MeshImportGen void add_tetra(ChunkArrayconst& pos,uint32 p0, uint32 p1, uint32 p2, uint32 p3, bool check_orientation) { if (check_orientation) - this->reoriente_tetra(pos,p0,p1,p2,p3); + this->reoriente_tetra(pos, p0, p1, p2, p3); this->volumes_types.push_back(VolumeType::Tetra); this->volumes_vertex_indices_.push_back(p0); this->volumes_vertex_indices_.push_back(p1); @@ -515,7 +554,7 @@ class VolumeImport : public MeshImportGen template inline void reoriente_tetra(ChunkArrayconst& pos, uint32& p0, uint32& p1, uint32& p2, uint32& p3) { - if (geometry::test_orientation_3D(pos[p0], pos[p1],pos[p2],pos[p3]) == geometry::Orientation3D::OVER) + if (geometry::test_orientation_3D(pos[p0], pos[p1], pos[p2], pos[p3]) == geometry::Orientation3D::OVER) std::swap(p1, p2); } @@ -524,7 +563,7 @@ class VolumeImport : public MeshImportGen { this->volumes_types.push_back(VolumeType::Pyramid); if (check_orientation) - this->reoriente_pyramid(pos,p0,p1,p2,p3,p4); + this->reoriente_pyramid(pos, p0, p1, p2, p3, p4); this->volumes_vertex_indices_.push_back(p0); this->volumes_vertex_indices_.push_back(p1); this->volumes_vertex_indices_.push_back(p2); @@ -535,7 +574,7 @@ class VolumeImport : public MeshImportGen template inline void reoriente_pyramid(ChunkArrayconst& pos, uint32& p0, uint32& p1, uint32& p2, uint32& p3, uint32& p4) { - if (geometry::test_orientation_3D(pos[p4], pos[p0],pos[p1],pos[p2]) == geometry::Orientation3D::OVER) + if (geometry::test_orientation_3D(pos[p4], pos[p0], pos[p1], pos[p2]) == geometry::Orientation3D::OVER) std::swap(p1, p3); } @@ -543,7 +582,7 @@ class VolumeImport : public MeshImportGen void add_triangular_prism(ChunkArrayconst& pos,uint32 p0, uint32 p1, uint32 p2, uint32 p3, uint32 p4, uint32 p5, bool check_orientation) { if (check_orientation) - this->reoriente_triangular_prism(pos,p0,p1,p2,p3,p4,p5); + this->reoriente_triangular_prism(pos, p0, p1, p2, p3, p4, p5); this->volumes_types.push_back(VolumeType::TriangularPrism); this->volumes_vertex_indices_.push_back(p0); this->volumes_vertex_indices_.push_back(p1); @@ -556,10 +595,10 @@ class VolumeImport : public MeshImportGen template inline void reoriente_triangular_prism(ChunkArrayconst& pos, uint32& p0, uint32& p1, uint32& p2, uint32& p3, uint32& p4, uint32& p5) { - if (geometry::test_orientation_3D(pos[p3], pos[p0],pos[p1],pos[p2]) == geometry::Orientation3D::OVER) + if (geometry::test_orientation_3D(pos[p3], pos[p0], pos[p1], pos[p2]) == geometry::Orientation3D::OVER) { - std::swap(p1,p2); - std::swap(p4,p5); + std::swap(p1, p2); + std::swap(p4, p5); } } @@ -573,12 +612,12 @@ class VolumeImport : public MeshImportGen } }; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_VOLUME_IMPORT_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_VOLUME_IMPORT_CPP_)) extern template class CGOGN_IO_API VolumeImport; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_VOLUME_IMPORT_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_VOLUME_IMPORT_CPP_)) } // namespace io } // namespace cgogn -#endif // IO_VOLUME_IMPORT_H_ +#endif // CGOGN_IO_VOLUME_IMPORT_H_ diff --git a/cgogn/io/vtk_io.cpp b/cgogn/io/vtk_io.cpp index 588468ae..3714cb91 100644 --- a/cgogn/io/vtk_io.cpp +++ b/cgogn/io/vtk_io.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_IO_DLL_EXPORT -#define IO_VTK_IO_CPP_ +#define CGOGN_IO_VTK_IO_CPP_ -#include +#include namespace cgogn { @@ -39,5 +39,7 @@ template class CGOGN_IO_API VtkVolumeImport; template class CGOGN_IO_API VtkVolumeImport; template class CGOGN_IO_API VtkVolumeImport>>; template class CGOGN_IO_API VtkVolumeImport>>; + +template class CGOGN_IO_API VtkVolumeExport>; } // namespace io } // namespace cgogn diff --git a/cgogn/io/vtk_io.h b/cgogn/io/vtk_io.h index d8afd73c..f92c3fea 100644 --- a/cgogn/io/vtk_io.h +++ b/cgogn/io/vtk_io.h @@ -21,19 +21,20 @@ * * *******************************************************************************/ -#ifndef IO_VTK_IO_H_ -#define IO_VTK_IO_H_ +#ifndef CGOGN_IO_VTK_IO_H_ +#define CGOGN_IO_VTK_IO_H_ #include #include +#include -#include - -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include namespace cgogn { @@ -41,36 +42,166 @@ namespace cgogn namespace io { -template -class VtkIO +enum VTK_CELL_TYPES +{ + VTK_VERTEX = 1, + VTK_POLY_VERTEX = 2, + VTK_LINE = 3, + VTK_POLY_LINE = 4, + VTK_TRIANGLE = 5, + VTK_TRIANGLE_STRIP = 6, + VTK_POLYGON = 7, + VTK_PIXEL = 8, + VTK_QUAD = 9, + + VTK_TETRA = 10, + VTK_VOXEL = 11, + VTK_HEXAHEDRON = 12, + VTK_WEDGE = 13, + VTK_PYRAMID = 14, + + VTK_QUADRATIC_EDGE = 21, + VTK_QUADRATIC_TRIANGLE = 22, + VTK_QUADRATIC_QUAD = 23, + VTK_QUADRATIC_TETRA = 24, + VTK_QUADRATIC_HEXAHEDRON = 25 +}; + +template +class VtkVolumeExport : public VolumeExport { -public : - enum VTK_CELL_TYPES +public: + using Inherit = VolumeExport; + using Self = VtkVolumeExport; + using Map = typename Inherit::Map; + using Vertex = typename Inherit::Vertex; + using Volume = typename Inherit::Volume; + using ChunkArrayGen = typename Inherit::ChunkArrayGen; + + +protected: + virtual void export_file_impl(const Map& map, std::ofstream& output, const ExportOptions& option) override { - VTK_VERTEX = 1, - VTK_POLY_VERTEX = 2, - VTK_LINE = 3, - VTK_POLY_LINE = 4, - VTK_TRIANGLE = 5, - VTK_TRIANGLE_STRIP = 6, - VTK_POLYGON = 7, - VTK_PIXEL = 8, - VTK_QUAD = 9, - - VTK_TETRA = 10, - VTK_VOXEL = 11, - VTK_HEXAHEDRON = 12, - VTK_WEDGE = 13, - VTK_PYRAMID = 14, - - VTK_QUADRATIC_EDGE = 21, - VTK_QUADRATIC_TRIANGLE = 22, - VTK_QUADRATIC_QUAD = 23, - VTK_QUADRATIC_TETRA = 24, - VTK_QUADRATIC_HEXAHEDRON = 25 - }; + ChunkArrayGen const* pos = this->get_position_attribute(); + const std::string endianness = cgogn::internal::cgogn_is_little_endian ? "LittleEndian" : "BigEndian"; + const std::string format = (option.binary_?"binary" :"ascii"); + std::string scalar_type = pos->get_nested_type_name(); + scalar_type[0] = std::toupper(scalar_type[0]); + + output << "" << std::endl; + output << "" << std::endl; + output << " " << std::endl; + output << " () << "\" NumberOfCells=\""<< (this->get_nb_tetras() + this->get_nb_pyramids() + this->get_nb_triangular_prisms() + this->get_nb_hexas()) << "\">" << std::endl; + + // 1st step : vertices + output << " " << std::endl; + // 1.a : positions + output << " get_name() << "\" NumberOfComponents=\"" << pos->get_nb_components() << "\" format=\"" << format << "\">" << std::endl; + map.foreach_cell([&](Vertex v) + { + output << " "; + pos->export_element(map.get_embedding(v), output, false); + output << std::endl; + }); + output << " " << std::endl; + output << " " << std::endl; + + if (!this->get_vertex_attributes().empty()) + { + output << " " << std::endl; + // 1.B : other vertices attributes + for (const auto& att : this->get_vertex_attributes()) + { + scalar_type = att->get_nested_type_name(); + scalar_type[0] = std::toupper(scalar_type[0]); + output << " get_name() << "\" NumberOfComponents=\"" << att->get_nb_components() << "\" format=\"" << format << "\">" << std::endl; + map.foreach_cell([&](Vertex v) + { + output << " "; + att->export_element(map.get_embedding(v), output, false); + output << std::endl; + }); + output << " " << std::endl; + } + output << " " << std::endl; + } + // end vertices + // begin volumes + output << " " << std::endl; + // 2.a. Connectivity + output << " " << std::endl; + + std::vector const& vertices_of_vol = this->get_vertices_of_volumes(); + std::vector const& nb_vert = this->get_number_of_vertices(); + std::size_t it = 0ul; + for(std::size_t i = 0ul, end = nb_vert.size() ; i < end; ++i) + { + output << " "; + for (std::size_t j = 0ul, nbv = nb_vert[i] ; j < nbv; ++j) + output << vertices_of_vol[it++] << " "; + output << std::endl; + } + + output << " " << std::endl; + // 2.b. offsets + output << " " << std::endl; + output << " "; + + std::size_t offset{0ul}; + for (std::size_t i=0ul; i" << std::endl; + // 2.c cell types + output << " " << std::endl; + output << " "; + + for (uint32 i=0u; i< this->get_nb_tetras(); ++i) + output << std::to_string(VTK_TETRA) << " "; + for (uint32 i=0u; i< this->get_nb_pyramids(); ++i) + output << std::to_string(VTK_PYRAMID) << " "; + for (uint32 i=0u; i< this->get_nb_triangular_prisms(); ++i) + output << std::to_string(VTK_WEDGE) << " "; + for (uint32 i=0u; i< this->get_nb_hexas(); ++i) + output << std::to_string(VTK_HEXAHEDRON) << " "; + + output << std::endl << " " << std::endl; + output << " " << std::endl; + + //2.d other volumes attributes + if (!this->get_volume_attributes().empty()) + { + output << " " << std::endl; + for (const auto& att : this->get_volume_attributes()) + { + scalar_type = att->get_nested_type_name(); + scalar_type[0] = std::toupper(scalar_type[0]); + output << " get_name() << "\" NumberOfComponents=\"" << att->get_nb_components() << "\" format=\"" << format << "\">" << std::endl; + for(std::size_t i = 0ul, end = nb_vert.size() ; i < end; ++i) + map.foreach_cell([&](Volume w) + { + output << " "; + att->export_element(map.get_embedding(w), output, false); + output << std::endl; + }); + output << " " << std::endl; + } + output << " " << std::endl; + } + output << " " << std::endl; + output << " " << std::endl; + output << "" << std::endl; + } +}; + +template +class VtkIO +{ +public: enum VTK_MESH_TYPE { UNKNOWN = 0, @@ -608,6 +739,35 @@ protected : cgogn_log_error("vtk_data_type_to_cgogn_name_of_type") << "Unknown vtk type \"" << vtk_type_str << "\"."; return std::string(); } + + template + static inline std::string vtk_name_of_type(const T& t) + { + static_assert(std::is_arithmetic::value, "T must be a scalar."); + if (std::is_same::value) + return "Int8"; + if (std::is_same::value) + return "UInt8"; + if (std::is_same::value) + return "Int16"; + if (std::is_same::value) + return "UInt16"; + if (std::is_same::value) + return "Int32"; + if (std::is_same::value) + return "UInt32"; + if (std::is_same::value) + return "Int64"; + if (std::is_same::value) + return "UInt64"; + if (std::is_same::value) + return "Float32"; + if (std::is_same::value) + return "Float64"; + + cgogn_log_error("vtk_name_of_type") << "Cannot convert to VTK the type \"" << cgogn::name_of_type(t) << "\"."; + return std::string(); + } }; @@ -621,7 +781,6 @@ class VtkSurfaceImport : public VtkIO: using DataInputGen = typename Inherit_Vtk::DataInputGen; template using DataInput = typename Inherit_Vtk::template DataInput; - using VTK_CELL_TYPES = typename Inherit_Vtk::VTK_CELL_TYPES; virtual ~VtkSurfaceImport() override {} protected: @@ -668,10 +827,12 @@ class VtkSurfaceImport : public VtkIO: virtual void add_vertex_attribute(const DataInputGen& attribute_data, const std::string& attribute_name) override { + cgogn_log_info("VtkSurfaceImport::add_vertex_attribute") << "Adding a vertex attribute named \"" << attribute_name << "\"."; attribute_data.to_chunk_array(attribute_data.add_attribute(this->vertex_attributes_, attribute_name)); } virtual void add_cell_attribute(const DataInputGen& attribute_data, const std::string& attribute_name) override { + cgogn_log_info("VtkSurfaceImport::add_cell_attribute") << "Adding a face attribute named \"" << attribute_name << "\"."; attribute_data.to_chunk_array(attribute_data.add_attribute(this->face_attributes_, attribute_name)); } virtual bool import_file_impl(const std::string& filename) override @@ -750,7 +911,6 @@ class VtkVolumeImport : public VtkIO:: using DataInputGen = typename Inherit_Vtk::DataInputGen; template using DataInput = typename Inherit_Vtk::template DataInput; - using VTK_CELL_TYPES = typename Inherit_Vtk::VTK_CELL_TYPES; template using ChunkArray = typename Inherit_Import::template ChunkArray; @@ -764,8 +924,8 @@ class VtkVolumeImport : public VtkIO:: if (!Inherit_Vtk::parse_vtk_legacy_file(fp)) return false; - this->nb_vertices_ = uint32(this->positions_.size()); - this->nb_volumes_ = uint32(this->cell_types_.size()); + this->set_nb_vertices(uint32(this->positions_.size())); + this->set_nb_volumes(uint32(this->cell_types_.size())); const std::vector* cell_types_vec = this->cell_types_.get_vec(); const std::vector* cells_vec = this->cells_.get_vec(); @@ -799,7 +959,7 @@ class VtkVolumeImport : public VtkIO:: } - add_vtk_volumes(cells_buffer,*cell_types_vec, *(this->vertex_attributes_.template get_attribute("position"))); + add_vtk_volumes(cells_buffer,*cell_types_vec, *(this->template get_position_attribute())); return true; } @@ -809,13 +969,13 @@ class VtkVolumeImport : public VtkIO:: if (!Inherit_Vtk::parse_xml_vtu(filename)) return false; - this->nb_vertices_ = uint32(this->positions_.size()); - this->nb_volumes_ = uint32(this->cell_types_.size()); + this->set_nb_vertices(uint32(this->positions_.size())); + this->set_nb_volumes(uint32(this->cell_types_.size())); const std::vector* cell_types_vec = this->cell_types_.get_vec(); const std::vector* cells_vec = this->cells_.get_vec(); - ChunkArray* pos = this->vertex_attributes_.template get_attribute("position"); + ChunkArray* pos = this->template get_position_attribute(); cgogn_assert(pos != nullptr); add_vtk_volumes(*cells_vec,*cell_types_vec, *pos); @@ -824,11 +984,13 @@ class VtkVolumeImport : public VtkIO:: virtual void add_vertex_attribute(const DataInputGen& attribute_data, const std::string& attribute_name) override { - attribute_data.to_chunk_array(attribute_data.add_attribute(this->vertex_attributes_, attribute_name)); + cgogn_log_info("VtkVolumeImport::add_vertex_attribute") << "Adding a vertex attribute named \"" << attribute_name << "\"."; + attribute_data.to_chunk_array(attribute_data.add_attribute(this->get_vertex_attributes_container(), attribute_name)); } virtual void add_cell_attribute(const DataInputGen& attribute_data, const std::string& attribute_name) override { - attribute_data.to_chunk_array(attribute_data.add_attribute(this->volume_attributes_, attribute_name)); + cgogn_log_info("VtkVolumeImport::add_cell_attribute") << "Adding a volume attribute named \"" << attribute_name << "\"."; + attribute_data.to_chunk_array(attribute_data.add_attribute(this->get_volume_attributes_container(), attribute_name)); } virtual bool import_file_impl(const std::string& filename) override @@ -851,7 +1013,7 @@ class VtkVolumeImport : public VtkIO:: inline void add_vtk_volumes(std::vector ids, const std::vector& type_vol, ChunkArray const& pos) { uint32 curr_offset = 0; - for (uint32 i=0u; i< this->nb_volumes_; ++i) + for (uint32 i=0u, end = this->get_nb_volumes(); i< end; ++i) { if (type_vol[i]== VTK_CELL_TYPES::VTK_HEXAHEDRON || type_vol[i]== VTK_CELL_TYPES::VTK_VOXEL) { @@ -885,7 +1047,7 @@ class VtkVolumeImport : public VtkIO:: } }; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_VTK_IO_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_VTK_IO_CPP_)) extern template class CGOGN_IO_API VtkIO; extern template class CGOGN_IO_API VtkIO; extern template class CGOGN_IO_API VtkIO>>; @@ -895,9 +1057,11 @@ extern template class CGOGN_IO_API VtkVolumeImport; extern template class CGOGN_IO_API VtkVolumeImport>>; extern template class CGOGN_IO_API VtkVolumeImport>>; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_VTK_IO_CPP_)) + +extern template class CGOGN_IO_API VtkVolumeExport>; +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_IO_VTK_IO_CPP_)) } // namespace io } // namespace cgogn -#endif // IO_VTK_IO_H_ +#endif // CGOGN_IO_VTK_IO_H_ diff --git a/cgogn/modeling/CMakeLists.txt b/cgogn/modeling/CMakeLists.txt index 8d4ed6b4..4e27e1ba 100644 --- a/cgogn/modeling/CMakeLists.txt +++ b/cgogn/modeling/CMakeLists.txt @@ -5,17 +5,16 @@ project(cgogn_modeling set(HEADER_FILES dll.h algos/catmull_clark.h + algos/pliant_remeshing.h + algos/loop.h ) - add_custom_target(cgogn_modeling SOURCES ${HEADER_FILES}) +add_custom_target(cgogn_modeling SOURCES ${HEADER_FILES}) #add_library(HEADER_ONLY_TARGET ${PROJECT_NAME} ${HEADER_FILES}) #set_target_properties(HEADER_ONLY_TARGET PROPERTIES LINKER_LANGUAGE CXX) -install(DIRECTORY . +install(FILES "dll.h" DESTINATION "include/cgogn/modeling") +install(DIRECTORY algos DESTINATION include/cgogn/modeling FILES_MATCHING PATTERN "*.h" ) - -if(CGOGN_BUILD_TESTS) - add_subdirectory(tests) -endif() diff --git a/cgogn/modeling/algos/catmull_clark.h b/cgogn/modeling/algos/catmull_clark.h index 84a5e67d..afeb061c 100644 --- a/cgogn/modeling/algos/catmull_clark.h +++ b/cgogn/modeling/algos/catmull_clark.h @@ -21,13 +21,12 @@ * * *******************************************************************************/ -#ifndef MODELING_ALGOS_H_ -#define MODELING_ALGOS_H_ +#ifndef CGOGN_MODELING_ALGOS_CATMULL_CLARK_H_ +#define CGOGN_MODELING_ALGOS_CATMULL_CLARK_H_ -//#include -#include -#include -#include +#include +#include +#include namespace cgogn { @@ -61,7 +60,7 @@ typename MAP::Vertex quadranguleFace(MAP& map, typename MAP::Face f) } template -void catmull_clark(MAP& map, typename MAP::template VertexAttributeHandler& position) +void catmull_clark(MAP& map, typename MAP::template VertexAttribute& position) { using Vertex = typename MAP::Vertex; using Edge = typename MAP::Edge; @@ -87,15 +86,9 @@ void catmull_clark(MAP& map, typename MAP::template VertexAttributeHandler for(Edge e: initial_edges) { -// Vertex v1(e.dart); -// Vertex v2(map.phi1(e.dart)); -// Vertex middle = map.cut_edge(e); -// position[middle] = (position[v1] + position[v2] )/Scalar(2); - std::pair ve = map.vertices(e); Vertex middle = map.cut_edge(e); position[middle] = (position[ve.first] + position[ve.second] )/Scalar(2); - } @@ -162,12 +155,10 @@ void catmull_clark(MAP& map, typename MAP::template VertexAttributeHandler position[v] += delta; } } - } - -} // namespace geometry +} // namespace modeling } // namespace cgogn -#endif // MODELING_ALGOS_H_ +#endif // CGOGN_MODELING_ALGOS_CATMULL_CLARK_H_ diff --git a/cgogn/modeling/algos/loop.h b/cgogn/modeling/algos/loop.h new file mode 100644 index 00000000..f0e6a588 --- /dev/null +++ b/cgogn/modeling/algos/loop.h @@ -0,0 +1,138 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef CGOGN_MODELING_ALGOS_LOOP_H_ +#define CGOGN_MODELING_ALGOS_LOOP_H_ + +#include + +#include + +namespace cgogn +{ + +namespace modeling +{ + +template +void loop(MAP& map, typename MAP::template VertexAttribute& position) +{ + using Vertex = typename MAP::Vertex; + using Edge = typename MAP::Edge; + using Face = typename MAP::Face; + using Scalar = typename VEC3::Scalar; + + typename MAP::template VertexAttribute position2 = map.template add_attribute("position_tempo_loop"); + + std::vector initial_edges; + std::vector initial_vertices; + + DartMarker initial_edge_marker(map); + + map.foreach_cell([&] (Edge e) + { + initial_edges.push_back(e); + initial_edge_marker.mark_orbit(e); + }); + + map.foreach_cell([&] (Vertex v) + { + initial_vertices.push_back(v); + }); + + // cut edges + for(Edge e: initial_edges) + { + std::pair ve = map.vertices(e); + map.cut_edge(e); + } + + // compute position of new edge points + for(Edge e: initial_edges) + { + Vertex v1(e.dart); + Vertex v2(map.template phi<12>(e.dart)); + Vertex nve(map.phi1(e.dart)); + Vertex vr(map.template phi<2111>(e.dart)); + Vertex vl(map.phi_1(map.phi_1(e.dart))); + + position2[nve] = Scalar(3.0/8.0)*(position[v1]+position[v2]) + Scalar(1.0/8.0)*(position[vr] + position[vl]); + } + + // compute new position of old vertices + for(Vertex v: initial_vertices) + { + VEC3 sum_edge;// Sum_E + sum_edge.setZero(); + + int nb_e = 0; + Dart bound; + map.foreach_incident_edge(v, [&] (Edge e) + { + nb_e++; + sum_edge += position[Vertex(map.template phi<12>(e.dart))]; + if (map.is_boundary(e.dart)) + bound = e.dart; + }); + + if (!bound.is_nil()) // boundary case + { + Vertex e1(map.phi2(bound)); + Vertex e2(map.phi_1(bound)); + position2[v] = Scalar(3.0/4.0)*position[v] + Scalar(1.0/8.0)*(position[e1]+position[e2]); + } + else + { + float64 beta = 3.0/16.0; + if (nb_e>3) + beta = 3.0/(8.0*nb_e); + position2[v] = Scalar(beta)*sum_edge + Scalar(1.0-beta*nb_e)*position[v]; + } + } + + // add edges inside faces + map.foreach_cell([&] (Face f) + { + Dart d0 = f.dart; + if (initial_edge_marker.is_marked(d0)) + d0 = map.phi1(d0); + + Dart d1 = map.template phi<11>(d0); + map.cut_face(Vertex(d0),Vertex(d1)); + + Dart d2 = map.template phi<11>(d1); + map.cut_face(Vertex(d1),Vertex(d2)); + + Dart d3 = map.template phi<11>(d2); + map.cut_face(Vertex(d2),Vertex(d3)); + }); + + map.swap_attributes(position,position2); + map.remove_attribute(position2); +} + +} // namespace modeling + +} // namespace cgogn + +#endif // CGOGN_MODELING_ALGOS_LOOP_H_ diff --git a/cgogn/modeling/algos/pliant_remeshing.h b/cgogn/modeling/algos/pliant_remeshing.h new file mode 100644 index 00000000..42c690a2 --- /dev/null +++ b/cgogn/modeling/algos/pliant_remeshing.h @@ -0,0 +1,147 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef CGOGN_MODELING_ALGOS_PLIANT_REMESHING_H_ +#define CGOGN_MODELING_ALGOS_PLIANT_REMESHING_H_ + +#include +#include +#include + +namespace cgogn +{ + +namespace modeling +{ + +template +void pliant_remeshing( + CMap2& map, + typename CMap2::template VertexAttribute& position +) +{ + using Scalar = typename VEC3::Scalar; + using Map = CMap2; + using Vertex = typename Map::Vertex; + using Edge = typename Map::Edge; + + Scalar mean_edge_length = 0; + + CellCache cache(map); + cache.template build(); + + // compute mean edge length + map.foreach_cell([&] (Edge e) + { + std::pair v = map.vertices(e); + const VEC3& edge = position[v.first] - position[v.second]; + mean_edge_length += edge.norm(); + }, + cache); + + mean_edge_length /= cache.template size(); + + const Scalar squared_max_edge_length = Scalar(0.5625) * mean_edge_length * mean_edge_length; // 0.5625 = 0.75^2 + const Scalar squared_min_edge_length = Scalar(1.5625) * mean_edge_length * mean_edge_length; // 1.5625 = 1.25^2 + + + // cut long edges (and adjacent faces) + map.foreach_cell([&] (Edge e) + { + std::pair v = map.vertices(e); + const VEC3& edge = position[v.first] - position[v.second]; + if(edge.squaredNorm() > squared_max_edge_length) + { + Dart e2 = map.phi2(e.dart); + Vertex nv = map.cut_edge(e); + position[nv] = Scalar(0.5) * (position[v.first] + position[v.second]); + map.cut_face(nv, Vertex(map.phi_1(e.dart))); + if(!map.is_boundary(e2)) + map.cut_face(Vertex(map.phi1(e2)), Vertex(map.phi_1(e2))); + } + }, + cache); + + // collapse short edges + + map.foreach_cell([&] (Edge e) + { + std::pair v = map.vertices(e); + const VEC3& edge = position[v.first] - position[v.second]; + if(edge.squaredNorm() < squared_min_edge_length) + { + bool collapse = true; + const VEC3& p = position[v.second]; + map.foreach_adjacent_vertex_through_edge(v.second, [&] (Vertex vv) + { + const VEC3& vec = p - position[vv]; + if (vec.squaredNorm() > squared_max_edge_length) + collapse = false; + }); + if(collapse) + { +// Vertex cv = map.collapse_edge(e); +// position[cv] = p; + } + } + }); + + // equalize valences with edge flips + typename Map::DartMarker dm(map); + map.foreach_cell( + [&] (Edge e) + { + map.flip_edge(e); // flip edge + const Dart d = e.dart; + const Dart d2 = map.phi2(d); + dm.mark_orbit(Edge(map.phi1(d))); + dm.mark_orbit(Edge(map.phi_1(d))); // mark adjacent + dm.mark_orbit(Edge(map.phi1(d2))); // edges + dm.mark_orbit(Edge(map.phi_1(d2))); + }, + // this filter only keeps edges that are not marked + // and whose incident vertices' degree meet some requirements + [&] (Edge e) -> bool + { + if (dm.is_marked(e.dart)) + return false; + std::pair v = map.vertices(e); + const uint32 w = map.degree(v.first); + const uint32 x = map.degree(v.second); + const uint32 y = map.degree(Vertex(map.phi1(map.phi1(v.first.dart)))); + const uint32 z = map.degree(Vertex(map.phi1(map.phi1(v.second.dart)))); + int32 flip = 0; + flip += w > 6 ? 1 : (w < 6 ? -1 : 0); + flip += x > 6 ? 1 : (x < 6 ? -1 : 0); + flip += y < 6 ? 1 : (y > 6 ? -1 : 0); + flip += z < 6 ? 1 : (z > 6 ? -1 : 0); + return flip > 1; + } + ); +} + +} // namespace modeling + +} // namespace cgogn + +#endif // CGOGN_MODELING_ALGOS_PLIANT_REMESHING_H_ diff --git a/cgogn/modeling/dll.h b/cgogn/modeling/dll.h index c002d1c0..6b642b3f 100644 --- a/cgogn/modeling/dll.h +++ b/cgogn/modeling/dll.h @@ -21,8 +21,8 @@ * * *******************************************************************************/ -#ifndef MODELING_DLL_H_ -#define MODELING_DLL_H_ +#ifndef CGOGN_MODELING_DLL_H_ +#define CGOGN_MODELING_DLL_H_ /** * \brief Linkage declaration for CGOGN symbols. @@ -37,4 +37,4 @@ #define CGOGN_MODELING_API #endif -#endif // MODELING_DLL_H_ +#endif // CGOGN_MODELING_DLL_H_ diff --git a/cgogn/modeling/examples/CMakeLists.txt b/cgogn/modeling/examples/CMakeLists.txt new file mode 100644 index 00000000..a6292546 --- /dev/null +++ b/cgogn/modeling/examples/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.0 FATAL_ERROR) + +project(cgogn_modeling_examples + LANGUAGES CXX +) + +find_package(cgogn_core REQUIRED) +find_package(cgogn_geometry REQUIRED) +find_package(cgogn_io REQUIRED) + +set(CGOGN_TEST_PREFIX "test_") +set(CGOGN_TEST_MESHES_PATH "${CMAKE_SOURCE_DIR}/data/meshes/") +add_definitions("-DCGOGN_TEST_MESHES_PATH=${CGOGN_TEST_MESHES_PATH}") + +add_executable(remeshing remeshing.cpp) +target_link_libraries(remeshing ${cgogn_core_LIBRARIES} ${cgogn_io_LIBRARIES} ${cgogn_geometry_LIBRARIES}) diff --git a/cgogn/modeling/examples/remeshing.cpp b/cgogn/modeling/examples/remeshing.cpp new file mode 100644 index 00000000..8b1261ce --- /dev/null +++ b/cgogn/modeling/examples/remeshing.cpp @@ -0,0 +1,34 @@ + +#include +#include +#include + +#define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) + +using Map2 = cgogn::CMap2; + +using Vec3 = Eigen::Vector3d; +//using Vec3 = cgogn::geometry::Vec_T>; + +template +using VertexAttribute = Map2::VertexAttribute; + +int main(int argc, char** argv) +{ + std::string surface_mesh; + if (argc < 2) + { + cgogn_log_info("cmap2_import") << "USAGE: " << argv[0] << " [filename]"; + surface_mesh = std::string(DEFAULT_MESH_PATH) + std::string("off/aneurysm_3D.off"); + cgogn_log_info("cmap2_import") << "Using default mesh : " << surface_mesh; + } + else + surface_mesh = std::string(argv[1]); + + Map2 map; + + cgogn::io::import_surface(map, surface_mesh); + + VertexAttribute vertex_position = map.get_attribute("position"); + cgogn::modeling::pliant_remeshing(map, vertex_position); +} diff --git a/cgogn/modeling/tests/CMakeLists.txt b/cgogn/modeling/tests/CMakeLists.txt index 5d9c6123..6864de1c 100644 --- a/cgogn/modeling/tests/CMakeLists.txt +++ b/cgogn/modeling/tests/CMakeLists.txt @@ -2,6 +2,9 @@ project(cgogn_modeling_test LANGUAGES CXX ) +find_package(cgogn_geometry REQUIRED) +find_package(cgogn_io REQUIRED) + set(SOURCE_FILES algos/catmull_clark_test.cpp main.cpp @@ -10,7 +13,7 @@ set(SOURCE_FILES add_definitions("-DCGOGN_TEST_MESHES_PATH=${CMAKE_SOURCE_DIR}/data/meshes/") add_executable(${PROJECT_NAME} ${SOURCE_FILES}) -target_link_libraries(cgogn_modeling_test gtest cgogn_geometry cgogn_io) +target_link_libraries(cgogn_modeling_test gtest ${cgogn_geometry_LIBRARIES} ${cgogn_io_LIBRARIES}) target_include_directories(cgogn_modeling_test PRIVATE ${CMAKE_SOURCE_DIR}/thirdparty/googletest-master/googletest/include) link_directories(${CMAKE_SOURCE_DIR}/thirdparty/googletest-master/googletest/lib) diff --git a/cgogn/modeling/tests/algos/catmull_clark_test.cpp b/cgogn/modeling/tests/algos/catmull_clark_test.cpp index 77b09bde..19cf313f 100644 --- a/cgogn/modeling/tests/algos/catmull_clark_test.cpp +++ b/cgogn/modeling/tests/algos/catmull_clark_test.cpp @@ -21,14 +21,13 @@ * * *******************************************************************************/ -#include - -#include +#include -#include +#include +#include +#include #include -#include #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) @@ -43,7 +42,7 @@ using VecTypes = testing::Types; using CMap2 = cgogn::CMap2; using Dart = cgogn::Dart; template -using VertexAttributeHandler = CMap2::VertexAttributeHandler; +using VertexAttribute = CMap2::VertexAttribute; using Vertex = CMap2::Vertex; using Edge = CMap2::Edge; using Face = CMap2::Face; @@ -58,7 +57,7 @@ protected : { using Scalar = typename cgogn::geometry::vector_traits::Scalar; - VertexAttributeHandler vertex_position = this->map2_.template get_attribute("position"); + VertexAttribute vertex_position = this->map2_.template get_attribute("position"); Scalar alpha = 0; Face f = map2_.add_face(n); @@ -78,7 +77,7 @@ TYPED_TEST(Algos_TEST, TriangleCatmullClark) { using Scalar = typename cgogn::geometry::vector_traits::Scalar; - VertexAttributeHandler vertex_position = this->map2_.template add_attribute("position"); + VertexAttribute vertex_position = this->map2_.template add_attribute("position"); this->add_polygone(3); @@ -98,7 +97,7 @@ TYPED_TEST(Algos_TEST, QuadCatmullClark) { using Scalar = typename cgogn::geometry::vector_traits::Scalar; - VertexAttributeHandler vertex_position = this->map2_.template add_attribute("position"); + VertexAttribute vertex_position = this->map2_.template add_attribute("position"); this->add_polygone(4); diff --git a/cgogn/multiresolution/CMakeLists.txt b/cgogn/multiresolution/CMakeLists.txt index 2eae3335..4f1cf747 100644 --- a/cgogn/multiresolution/CMakeLists.txt +++ b/cgogn/multiresolution/CMakeLists.txt @@ -2,6 +2,9 @@ project(cgogn_multiresolution LANGUAGES CXX ) +find_package(cgogn_core REQUIRED) +find_package(cgogn_geometry REQUIRED) + set(HEADER_FILES dll.h @@ -38,21 +41,15 @@ set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "_d") target_include_directories(${PROJECT_NAME} PUBLIC $ - $ + $ ) -target_link_libraries(${PROJECT_NAME} cgogn_core cgogn_geometry) +target_link_libraries(${PROJECT_NAME} ${cgogn_core_LIBRARIES} ${cgogn_geometry_LIBRARIES}) -install(DIRECTORY . +install(FILES "dll.h" DESTINATION "include/cgogn/multiresolution") +install(DIRECTORY cph rcmap DESTINATION include/cgogn/multiresolution FILES_MATCHING PATTERN "*.h" ) -install(TARGETS ${PROJECT_NAME} - EXPORT ${PROJECT_NAME}Targets - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib -) - -#add_subdirectory(examples) +cgogn_create_package("${CGOGN_SOURCE_DIR}" "include") diff --git a/cgogn/multiresolution/cph/attribute_handler_cph.h b/cgogn/multiresolution/cph/attribute_handler_cph.h index 7d4da360..58d42a7a 100644 --- a/cgogn/multiresolution/cph/attribute_handler_cph.h +++ b/cgogn/multiresolution/cph/attribute_handler_cph.h @@ -21,26 +21,26 @@ * * *******************************************************************************/ -#ifndef MULTIRESOLUTION_CPH_ATTRIBUTE_HANDLER_CPH_H_ -#define MULTIRESOLUTION_CPH_ATTRIBUTE_HANDLER_CPH_H_ +#ifndef CGOGN_MULTIRESOLUTION_CPH_ATTRIBUTE_HANDLER_CPH_H_ +#define CGOGN_MULTIRESOLUTION_CPH_ATTRIBUTE_HANDLER_CPH_H_ -#include -#include +#include +#include namespace cgogn { /** - * \brief AttributeHandler class + * \brief Attribute class * @TPARAM T the data type of the attribute to handlde */ template -class AttributeHandlerCPH : public AttributeHandler +class AttributeCPH : public Attribute { public: - using Inherit = AttributeHandler; - using Self = AttributeHandlerCPH; + using Inherit = Attribute; + using Self = AttributeCPH; using value_type = T; @@ -48,19 +48,19 @@ class AttributeHandlerCPH : public AttributeHandler using TChunkArray = typename Inherit::template ChunkArray; - AttributeHandlerCPH() : + AttributeCPH() : Inherit() {} - AttributeHandlerCPH(MapData* const m, TChunkArray* const ca) : + AttributeCPH(MapData* const m, TChunkArray* const ca) : Inherit(m,ca) {} - AttributeHandlerCPH(const Self& att) : + AttributeCPH(const Self& att) : Inherit(att) {} - AttributeHandlerCPH(Self&& att) CGOGN_NOEXCEPT : + AttributeCPH(Self&& att) CGOGN_NOEXCEPT : Inherit(att) {} @@ -76,7 +76,7 @@ class AttributeHandlerCPH : public AttributeHandler T& operator[](Cell c) { - cgogn_message_assert(is_valid(), "Invalid AttributeHandler"); + cgogn_message_assert(is_valid(), "Invalid Attribute"); return this->chunk_array_->operator[](this->map_->get_embedding(c)); } // switch(ORBIT) @@ -100,12 +100,12 @@ class AttributeHandlerCPH : public AttributeHandler // { // step++ ; // uint32 nextIdx = m->m_nextLevelCell[orbit]->operator[](index) ; -// if (nextIdx == EMBNULL) +// if (nextIdx == INVALID_INDEX) // { // nextIdx = m->newCell() ; // m->copyCell(nextIdx, index) ; // m->m_nextLevelCell[orbit]->operator[](index) = nextIdx ; -// m->m_nextLevelCell[orbit]->operator[](nextIdx) = EMBNULL ; +// m->m_nextLevelCell[orbit]->operator[](nextIdx) = INVALID_INDEX ; // cont.refLine(index) ; // } // index = nextIdx ; @@ -129,7 +129,7 @@ class AttributeHandlerCPH : public AttributeHandler // { // step++ ; // uint32 next = m->m_nextLevelCell[orbit]->operator[](index) ; -// if(next != EMBNULL) index = next ; +// if(next != INVALID_INDEX) index = next ; // else break ; // } // return this->m_attrib->operator[](index); @@ -137,15 +137,15 @@ class AttributeHandlerCPH : public AttributeHandler T& operator[](uint32 a) { - return AttributeHandler::operator[](a) ; + return Attribute::operator[](a) ; } const T& operator[](uint32 a) const { - return AttributeHandler::operator[](a) ; + return Attribute::operator[](a) ; } }; } // namespace cgogn -#endif // MULTIRESOLUTION_CPH_ATTRIBUTE_HANDLER_CPH_H_ +#endif // CGOGN_MULTIRESOLUTION_CPH_ATTRIBUTE_HANDLER_CPH_H_ diff --git a/cgogn/multiresolution/cph/cph2.cpp b/cgogn/multiresolution/cph/cph2.cpp index 0d51adb5..0c95d777 100644 --- a/cgogn/multiresolution/cph/cph2.cpp +++ b/cgogn/multiresolution/cph/cph2.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_MULTIRESOLUTION_DLL_EXPORT -#define MULTIRESOLUTION_CPH_CPH2_CPP_ +#define CGOGN_MULTIRESOLUTION_CPH_CPH2_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/multiresolution/cph/cph2.h b/cgogn/multiresolution/cph/cph2.h index c80ccbe8..69498c8d 100644 --- a/cgogn/multiresolution/cph/cph2.h +++ b/cgogn/multiresolution/cph/cph2.h @@ -21,10 +21,10 @@ * * *******************************************************************************/ -#ifndef MULTIRESOLUTION_CPH_CPH2_BASE_H_ -#define MULTIRESOLUTION_CPH_CPH2_BASE_H_ +#ifndef CGOGN_MULTIRESOLUTION_CPH_CPH2_BASE_H_ +#define CGOGN_MULTIRESOLUTION_CPH_CPH2_BASE_H_ -#include +#include namespace cgogn { @@ -105,10 +105,10 @@ class CPH2 : public CPHBase }; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_CPH2_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_MULTIRESOLUTION_CPH_CPH2_CPP_)) extern template class CGOGN_MULTIRESOLUTION_API CPH2; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_CPH2_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_MULTIRESOLUTION_CPH_CPH2_CPP_)) } // namespace cgogn -#endif // MULTIRESOLUTION_CPH_CPH2_BASE_H_ +#endif // CGOGN_MULTIRESOLUTION_CPH_CPH2_BASE_H_ diff --git a/cgogn/multiresolution/cph/cph3.cpp b/cgogn/multiresolution/cph/cph3.cpp index ff6ce2c2..35887320 100644 --- a/cgogn/multiresolution/cph/cph3.cpp +++ b/cgogn/multiresolution/cph/cph3.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_MULTIRESOLUTION_DLL_EXPORT -#define MULTIRESOLUTION_CPH_CPH3_CPP_ +#define CGOGN_MULTIRESOLUTION_CPH_CPH3_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/multiresolution/cph/cph3.h b/cgogn/multiresolution/cph/cph3.h index 5d9e0c18..8db90510 100644 --- a/cgogn/multiresolution/cph/cph3.h +++ b/cgogn/multiresolution/cph/cph3.h @@ -21,10 +21,10 @@ * * *******************************************************************************/ -#ifndef MULTIRESOLUTION_CPH_CPH3_BASE_H_ -#define MULTIRESOLUTION_CPH_CPH3_BASE_H_ +#ifndef CGOGN_MULTIRESOLUTION_CPH_CPH3_BASE_H_ +#define CGOGN_MULTIRESOLUTION_CPH_CPH3_BASE_H_ -#include +#include namespace cgogn { @@ -78,10 +78,10 @@ class CPH3 : public CPH2 } }; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_CPH3_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_MULTIRESOLUTION_CPH_CPH3_CPP_)) extern template class CGOGN_MULTIRESOLUTION_API CPH3; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_CPH3_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_MULTIRESOLUTION_CPH_CPH3_CPP_)) } // namespace cgogn -#endif // MULTIRESOLUTION_CPH_CPH3_BASE_H_ +#endif // CGOGN_MULTIRESOLUTION_CPH_CPH3_BASE_H_ diff --git a/cgogn/multiresolution/cph/cph_base.cpp b/cgogn/multiresolution/cph/cph_base.cpp index 27e52159..502c9f98 100644 --- a/cgogn/multiresolution/cph/cph_base.cpp +++ b/cgogn/multiresolution/cph/cph_base.cpp @@ -20,10 +20,10 @@ * Contact information: cgogn@unistra.fr * * * *******************************************************************************/ -#define MULTIRESOLUTION_CPH_CPH_BASE_CPP_ +#define CGOGN_MULTIRESOLUTION_CPH_CPH_BASE_CPP_ #define CGOGN_MULTIRESOLUTION_DLL_EXPORT -#include +#include namespace cgogn { diff --git a/cgogn/multiresolution/cph/cph_base.h b/cgogn/multiresolution/cph/cph_base.h index c55a4e9a..861470c2 100644 --- a/cgogn/multiresolution/cph/cph_base.h +++ b/cgogn/multiresolution/cph/cph_base.h @@ -21,15 +21,15 @@ * * *******************************************************************************/ -#ifndef MULTIRESOLUTION_CPH_CPH_BASE_H_ -#define MULTIRESOLUTION_CPH_CPH_BASE_H_ +#ifndef CGOGN_MULTIRESOLUTION_CPH_CPH_BASE_H_ +#define CGOGN_MULTIRESOLUTION_CPH_CPH_BASE_H_ -#include -#include -#include -#include +#include +#include +#include +#include -#include +#include namespace cgogn { @@ -147,11 +147,11 @@ class CPHBase }; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_CPH_BASE_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_MULTIRESOLUTION_CPH_CPH_BASE_CPP_)) extern template class CGOGN_MULTIRESOLUTION_API CPHBase; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_CPH_BASE_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_MULTIRESOLUTION_CPH_CPH_BASE_CPP_)) } // namespace cgogn -#endif // MULTIRESOLUTION_CPH_CPH_BASE_H_ +#endif // CGOGN_MULTIRESOLUTION_CPH_CPH_BASE_H_ diff --git a/cgogn/multiresolution/cph/ihcmap2.cpp b/cgogn/multiresolution/cph/ihcmap2.cpp index 09028488..d4a84715 100644 --- a/cgogn/multiresolution/cph/ihcmap2.cpp +++ b/cgogn/multiresolution/cph/ihcmap2.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_MULTIRESOLUTION_DLL_EXPORT -#define MULTIRESOLUTION_CPH_IHCMAP2_CPP_ +#define CGOGN_MULTIRESOLUTION_CPH_IHCMAP2_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/multiresolution/cph/ihcmap2.h b/cgogn/multiresolution/cph/ihcmap2.h index f4a4c953..a21dd577 100644 --- a/cgogn/multiresolution/cph/ihcmap2.h +++ b/cgogn/multiresolution/cph/ihcmap2.h @@ -21,11 +21,11 @@ * * *******************************************************************************/ -#ifndef MULTIRESOLUTION_CPH_IHCMAP2_H_ -#define MULTIRESOLUTION_CPH_IHCMAP2_H_ +#ifndef CGOGN_MULTIRESOLUTION_CPH_IHCMAP2_H_ +#define CGOGN_MULTIRESOLUTION_CPH_IHCMAP2_H_ -#include -#include +#include +#include namespace cgogn { @@ -60,17 +60,17 @@ class IHCMap2_T : public CMap2_T, public CPH2 using ChunkArrayContainer = typename Inherit_CMAP::template ChunkArrayContainer; template - using AttributeHandler = typename Inherit_CMAP::template AttributeHandler; + using Attribute = typename Inherit_CMAP::template Attribute; template - using DartAttributeHandler = AttributeHandler; + using DartAttribute = Attribute; template - using VertexAttributeHandler = AttributeHandler; + using VertexAttribute = Attribute; template - using EdgeAttributeHandler = AttributeHandler; + using EdgeAttribute = Attribute; template - using FaceAttributeHandler = AttributeHandler; + using FaceAttribute = Attribute; template - using VolumeAttributeHandler = AttributeHandler; + using VolumeAttribute = Attribute; using DartMarker = typename cgogn::DartMarker; using DartMarkerStore = typename cgogn::DartMarkerStore; @@ -195,7 +195,7 @@ class IHCMap2_T : public CMap2_T, public CPH2 // step++; // uint32 next = next_level_cell_[ORBIT]->operator[](index); // //index = next; -// if(next != EMBNULL) index = next; +// if(next != INVALID_INDEX) index = next; // else break; // } @@ -345,10 +345,10 @@ struct IHCMap2Type template using IHCMap2 = IHCMap2_T>; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_IHCMAP2_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_MULTIRESOLUTION_CPH_IHCMAP2_CPP_)) extern template class CGOGN_MULTIRESOLUTION_API IHCMap2_T>; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_IHCMAP2_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_MULTIRESOLUTION_CPH_IHCMAP2_CPP_)) } // namespace cgogn -#endif // MULTIRESOLUTION_CPH_IHCMAP2_H_ +#endif // CGOGN_MULTIRESOLUTION_CPH_IHCMAP2_H_ diff --git a/cgogn/multiresolution/cph/ihcmap2_adaptive.cpp b/cgogn/multiresolution/cph/ihcmap2_adaptive.cpp index b22ef849..7c340054 100644 --- a/cgogn/multiresolution/cph/ihcmap2_adaptive.cpp +++ b/cgogn/multiresolution/cph/ihcmap2_adaptive.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_MULTIRESOLUTION_DLL_EXPORT -#define MULTIRESOLUTION_CPH_IHCMAP2_ADAPTIVE_CPP_ +#define CGOGN_MULTIRESOLUTION_CPH_IHCMAP2_ADAPTIVE_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/multiresolution/cph/ihcmap2_adaptive.h b/cgogn/multiresolution/cph/ihcmap2_adaptive.h index fb02422e..094e36a1 100644 --- a/cgogn/multiresolution/cph/ihcmap2_adaptive.h +++ b/cgogn/multiresolution/cph/ihcmap2_adaptive.h @@ -21,10 +21,10 @@ * * *******************************************************************************/ -#ifndef MULTIRESOLUTION_CPH_IHCMAP2_ADAPTIVE_H_ -#define MULTIRESOLUTION_CPH_IHCMAP2_ADAPTIVE_H_ +#ifndef CGOGN_MULTIRESOLUTION_CPH_IHCMAP2_ADAPTIVE_H_ +#define CGOGN_MULTIRESOLUTION_CPH_IHCMAP2_ADAPTIVE_H_ -#include +#include namespace cgogn { @@ -578,11 +578,11 @@ struct IHCMap2AdaptiveType template using IHCMap2Adaptive = IHCMap2Adaptive_T>; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_IHCMAP2_ADAPTIVE_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_MULTIRESOLUTION_CPH_IHCMAP2_ADAPTIVE_CPP_)) extern template class CGOGN_MULTIRESOLUTION_API IHCMap2Adaptive_T>; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_IHCMAP2_ADAPTIVE_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_MULTIRESOLUTION_CPH_IHCMAP2_ADAPTIVE_CPP_)) } // namespace cgogn -#endif // MULTIRESOLUTION_CPH_IHCMAP2_ADAPTIVE_H_ +#endif // CGOGN_MULTIRESOLUTION_CPH_IHCMAP2_ADAPTIVE_H_ diff --git a/cgogn/multiresolution/cph/ihcmap2_regular.cpp b/cgogn/multiresolution/cph/ihcmap2_regular.cpp index d9283b98..76086a35 100644 --- a/cgogn/multiresolution/cph/ihcmap2_regular.cpp +++ b/cgogn/multiresolution/cph/ihcmap2_regular.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_MULTIRESOLUTION_DLL_EXPORT -#define MULTIRESOLUTION_CPH_IHCMAP2_REGULAR_CPP_ +#define CGOGN_MULTIRESOLUTION_CPH_IHCMAP2_REGULAR_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/multiresolution/cph/ihcmap2_regular.h b/cgogn/multiresolution/cph/ihcmap2_regular.h index f1d174d5..f3c919a3 100644 --- a/cgogn/multiresolution/cph/ihcmap2_regular.h +++ b/cgogn/multiresolution/cph/ihcmap2_regular.h @@ -21,10 +21,10 @@ * * *******************************************************************************/ -#ifndef MULTIRESOLUTION_CPH_IHCMAP2_REGULAR_H_ -#define MULTIRESOLUTION_CPH_IHCMAP2_REGULAR_H_ +#ifndef CGOGN_MULTIRESOLUTION_CPH_IHCMAP2_REGULAR_H_ +#define CGOGN_MULTIRESOLUTION_CPH_IHCMAP2_REGULAR_H_ -#include +#include namespace cgogn { @@ -285,10 +285,10 @@ struct IHCMap2RegularType template using IHCMap2Regular = IHCMap2Regular_T>; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_IHCMAP2_REGULAR_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_MULTIRESOLUTION_CPH_IHCMAP2_REGULAR_CPP_)) extern template class CGOGN_MULTIRESOLUTION_API IHCMap2Regular_T>; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_IHCMAP2_REGULAR_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_MULTIRESOLUTION_CPH_IHCMAP2_REGULAR_CPP_)) } // namespace cgogn -#endif // MULTIRESOLUTION_CPH_IHCMAP2_REGULAR_H_ +#endif // CGOGN_MULTIRESOLUTION_CPH_IHCMAP2_REGULAR_H_ diff --git a/cgogn/multiresolution/cph/ihcmap3.cpp b/cgogn/multiresolution/cph/ihcmap3.cpp index 0bacad5c..57ea1f84 100644 --- a/cgogn/multiresolution/cph/ihcmap3.cpp +++ b/cgogn/multiresolution/cph/ihcmap3.cpp @@ -22,9 +22,9 @@ *******************************************************************************/ #define CGOGN_MULTIRESOLUTION_DLL_EXPORT -#define MULTIRESOLUTION_CPH_IHCMAP3_CPP_ +#define CGOGN_MULTIRESOLUTION_CPH_IHCMAP3_CPP_ -#include +#include namespace cgogn { diff --git a/cgogn/multiresolution/cph/ihcmap3.h b/cgogn/multiresolution/cph/ihcmap3.h index 79f2a635..3ed3d7c9 100644 --- a/cgogn/multiresolution/cph/ihcmap3.h +++ b/cgogn/multiresolution/cph/ihcmap3.h @@ -21,11 +21,11 @@ * * *******************************************************************************/ -#ifndef MULTIRESOLUTION_CPH_IHCMAP3_H_ -#define MULTIRESOLUTION_CPH_IHCMAP3_H_ +#ifndef CGOGN_MULTIRESOLUTION_CPH_IHCMAP3_H_ +#define CGOGN_MULTIRESOLUTION_CPH_IHCMAP3_H_ -#include -#include +#include +#include namespace cgogn { @@ -63,17 +63,17 @@ class IHCMap3_T :public CMap3_T, public CPH3 using ChunkArrayContainer = typename Inherit_CMAP::template ChunkArrayContainer; template - using AttributeHandler = typename Inherit_CMAP::template AttributeHandler; + using Attribute = typename Inherit_CMAP::template Attribute; template - using DartAttributeHandler = AttributeHandler; + using DartAttribute = Attribute; template - using VertexAttributeHandler = AttributeHandler; + using VertexAttribute = Attribute; template - using EdgeAttributeHandler = AttributeHandler; + using EdgeAttribute = Attribute; template - using FaceAttributeHandler = AttributeHandler; + using FaceAttribute = Attribute; template - using VolumeAttributeHandler = AttributeHandler; + using VolumeAttribute = Attribute; using DartMarker = typename cgogn::DartMarker; using DartMarkerStore = typename cgogn::DartMarkerStore; @@ -334,7 +334,8 @@ class IHCMap3_T :public CMap3_T, public CPH3 static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21 || - ORBIT == Orbit::PHI1_PHI3 || ORBIT == Orbit::PHI2_PHI3 || ORBIT == Orbit::PHI21_PHI31, + ORBIT == Orbit::PHI1_PHI3 || ORBIT == Orbit::PHI2_PHI3 || ORBIT == Orbit::PHI21_PHI31 || + ORBIT == Orbit::PHI1_PHI2_PHI3, "Orbit not supported in a IHCMap3"); switch (ORBIT) @@ -347,6 +348,7 @@ class IHCMap3_T :public CMap3_T, public CPH3 case Orbit::PHI2_PHI3: foreach_dart_of_PHI2_PHI3(c.dart, f); break; case Orbit::PHI21: foreach_dart_of_PHI21(c.dart, f); break; case Orbit::PHI21_PHI31: foreach_dart_of_PHI21_PHI31(c.dart, f); break; + case Orbit::PHI1_PHI2_PHI3: foreach_dart_of_PHI1_PHI2_PHI3(c.dart, f); break; default: cgogn_assert_not_reached("Cells of this dimension are not handled"); break; } } @@ -362,11 +364,11 @@ struct IHCMap3Type template using IHCMap3 = IHCMap3_T>; -#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_IHCMAP3_CPP_)) +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_MULTIRESOLUTION_CPH_IHCMAP3_CPP_)) extern template class CGOGN_MULTIRESOLUTION_API IHCMap3_T>; -#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_IHCMAP3_CPP_)) +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CGOGN_MULTIRESOLUTION_CPH_IHCMAP3_CPP_)) } // namespace cgogn -#endif // MULTIRESOLUTION_CPH_IHCMAP3_H_ +#endif // CGOGN_MULTIRESOLUTION_CPH_IHCMAP3_H_ diff --git a/cgogn/multiresolution/dll.h b/cgogn/multiresolution/dll.h index dec04f49..72fa6b6f 100644 --- a/cgogn/multiresolution/dll.h +++ b/cgogn/multiresolution/dll.h @@ -21,8 +21,8 @@ * * *******************************************************************************/ -#ifndef MULTIRESOLUTION_DLL_H_ -#define MULTIRESOLUTION_DLL_H_ +#ifndef CGOGN_MULTIRESOLUTION_DLL_H_ +#define CGOGN_MULTIRESOLUTION_DLL_H_ /** * \brief Linkage declaration for CGOGN symbols. @@ -37,4 +37,4 @@ #define CGOGN_MULTIRESOLUTION_API #endif -#endif // MULTIRESOLUTION_DLL_H_ +#endif // CGOGN_MULTIRESOLUTION_DLL_H_ diff --git a/cgogn/multiresolution/mrcmap/mr_base.h b/cgogn/multiresolution/mrcmap/mr_base.h index d7eb1b3e..cb808641 100644 --- a/cgogn/multiresolution/mrcmap/mr_base.h +++ b/cgogn/multiresolution/mrcmap/mr_base.h @@ -21,14 +21,14 @@ * * *******************************************************************************/ -#ifndef MULTIRESOLUTION_MRCMAP_MR_BASE_H_ -#define MULTIRESOLUTION_MRCMAP_MR_BASE_H_ +#ifndef CGOGN_MULTIRESOLUTION_MRCMAP_MR_BASE_H_ +#define CGOGN_MULTIRESOLUTION_MRCMAP_MR_BASE_H_ #include #include #include -#include +#include namespace cgogn { @@ -167,4 +167,4 @@ class MRBase } -#endif // MULTIRESOLUTION_MRCMAP_MR_BASE_H_ +#endif // CGOGN_MULTIRESOLUTION_MRCMAP_MR_BASE_H_ diff --git a/cgogn/multiresolution/mrcmap/mrcmap2.h b/cgogn/multiresolution/mrcmap/mrcmap2.h index 62079a43..94d65ed3 100644 --- a/cgogn/multiresolution/mrcmap/mrcmap2.h +++ b/cgogn/multiresolution/mrcmap/mrcmap2.h @@ -21,11 +21,11 @@ * * *******************************************************************************/ -#ifndef MULTIRESOLUTION_MRCMAP_MRCMAP2_H_ -#define MULTIRESOLUTION_MRCMAP_MRCMAP2_H_ +#ifndef CGOGN_MULTIRESOLUTION_MRCMAP_MRCMAP2_H_ +#define CGOGN_MULTIRESOLUTION_MRCMAP_MRCMAP2_H_ -#include -#include +#include +#include namespace cgogn { @@ -124,4 +124,4 @@ using MRCMap2 = MRCMap2_T>; } // namespace cgogn -#endif // MULTIRESOLUTION_MRCMAP_MRCMAP2_H_ +#endif // CGOGN_MULTIRESOLUTION_MRCMAP_MRCMAP2_H_ diff --git a/cgogn/rendering/CMakeLists.txt b/cgogn/rendering/CMakeLists.txt index ae753eba..e167d658 100644 --- a/cgogn/rendering/CMakeLists.txt +++ b/cgogn/rendering/CMakeLists.txt @@ -1,9 +1,10 @@ project(cgogn_rendering LANGUAGES CXX - ) +) -find_package(Qt5Widgets) -#find_package(Qt5OpenGL) +find_package(cgogn_core REQUIRED) +find_package(cgogn_geometry REQUIRED) +find_package(Qt5 COMPONENTS Widgets REQUIRED) set(HEADER_FILES dll.h @@ -20,10 +21,12 @@ set(HEADER_FILES shaders/shader_point_sprite.h shaders/shader_explode_volumes.h shaders/shader_explode_volumes_line.h + shaders/shader_texture.h drawer.h - topo_render.h - volume_render.h - ) + topo_drawer.h + volume_drawer.h + wall_paper.h +) set(SOURCE_FILES shaders/shader_program.cpp @@ -37,11 +40,13 @@ set(SOURCE_FILES shaders/shader_point_sprite.cpp shaders/shader_explode_volumes.cpp shaders/shader_explode_volumes_line.cpp + shaders/shader_texture.cpp drawer.cpp - topo_render.cpp - volume_render.cpp + topo_drawer.cpp + volume_drawer.cpp map_render.cpp - ) + wall_paper.cpp +) add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) @@ -51,28 +56,17 @@ target_include_directories(${PROJECT_NAME} PUBLIC $ $ $ - $ - ) + $ +) +target_link_libraries(${PROJECT_NAME} ${cgogn_core_LIBRARIES} ${cgogn_geometry_LIBRARIES} ${Qt5Widgets_LIBRARIES}) -target_link_libraries(${PROJECT_NAME} cgogn_core cgogn_geometry Qt5::Widgets) - -install(DIRECTORY . +file(GLOB HEADERS "." "*.h") +install(FILES ${HEADERS} + DESTINATION include/cgogn/rendering) +install(DIRECTORY shaders DESTINATION include/cgogn/rendering FILES_MATCHING PATTERN "*.h" - ) - -install(TARGETS ${PROJECT_NAME} - EXPORT ${PROJECT_NAME}Targets - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib - ) - -add_subdirectory(examples) - -#if(CGOGN_BUILD_TESTS) -# add_subdirectory(tests) -#endif() - +) +cgogn_create_package("${CGOGN_SOURCE_DIR}" "include") diff --git a/cgogn/rendering/dll.h b/cgogn/rendering/dll.h index 32811c34..b009963e 100644 --- a/cgogn/rendering/dll.h +++ b/cgogn/rendering/dll.h @@ -21,8 +21,8 @@ * * *******************************************************************************/ -#ifndef RENDERING_DLL_H_ -#define RENDERING_DLL_H_ +#ifndef CGOGN_RENDERING_DLL_H_ +#define CGOGN_RENDERING_DLL_H_ /** * \brief Linkage declaration for CGOGN symbols. @@ -37,4 +37,4 @@ #define CGOGN_RENDERING_API #endif -#endif // RENDERING_DLL_H_ +#endif // CGOGN_RENDERING_DLL_H_ diff --git a/cgogn/rendering/drawer.cpp b/cgogn/rendering/drawer.cpp index 8c0ce27c..77d1f727 100644 --- a/cgogn/rendering/drawer.cpp +++ b/cgogn/rendering/drawer.cpp @@ -23,11 +23,12 @@ #define CGOGN_RENDERING_DLL_EXPORT -#include +#include #include +#include + #include -#include namespace cgogn { @@ -35,71 +36,19 @@ namespace cgogn namespace rendering { -// static members init -ShaderColorPerVertex* Drawer::shader_cpv_ = nullptr; -ShaderBoldLine* Drawer::shader_bl_ = nullptr; -ShaderRoundPoint* Drawer::shader_rp_ = nullptr; -ShaderPointSprite* Drawer::shader_ps_ = nullptr; -int32 Drawer::nb_instances_ = 0; - -Drawer::Drawer(QOpenGLFunctions_3_3_Core* ogl33): +DisplayListDrawer::DisplayListDrawer(): current_size_(1.0f), current_aa_(true), - current_ball_(true), - ogl33_(ogl33) + current_ball_(true) { - nb_instances_++; - - vbo_pos_ = new VBO(3); - vbo_col_ = new VBO(3); - if (!shader_cpv_) - shader_cpv_ = new ShaderColorPerVertex(); - - vao_cpv_ = shader_cpv_->add_vao(); - shader_cpv_->set_vao(vao_cpv_,vbo_pos_,vbo_col_); - - if (!shader_bl_) - shader_bl_ = new ShaderBoldLine(true); - vao_bl_ = shader_bl_->add_vao(); - shader_bl_->bind(); - shader_bl_->release(); - shader_bl_->set_vao(vao_bl_,vbo_pos_,vbo_col_); - - if (!shader_rp_) - shader_rp_ = new ShaderRoundPoint(true); - vao_rp_ = shader_rp_->add_vao(); - shader_rp_->bind(); - shader_rp_->release(); - shader_rp_->set_vao(vao_rp_,vbo_pos_,vbo_col_); - - if (!shader_ps_) - shader_ps_ = new ShaderPointSprite(true); - vao_ps_ = shader_ps_->add_vao(); - shader_ps_->bind(); - shader_ps_->release(); - shader_ps_->set_vao(vao_ps_,vbo_pos_,vbo_col_); - - + vbo_pos_ = cgogn::make_unique(3); + vbo_col_ = cgogn::make_unique(3); } -Drawer::~Drawer() -{ - delete vbo_pos_; - delete vbo_col_; - - nb_instances_--; - if (nb_instances_ == 0) - { - // delete shaders when last drawer is deleted - // ensure context still enable when delete shaders - delete shader_ps_; - delete shader_rp_; - delete shader_bl_; - delete shader_cpv_; - } -} +DisplayListDrawer::~DisplayListDrawer() +{} -void Drawer::new_list() +void DisplayListDrawer::new_list() { data_pos_.clear(); data_col_.clear(); @@ -111,56 +60,54 @@ void Drawer::new_list() begins_face_.clear(); } -void Drawer::begin(GLenum mode) +void DisplayListDrawer::begin(GLenum mode) { switch (mode) { case GL_POINTS: if (current_ball_) { - begins_balls_.push_back(PrimParam(data_pos_.size(), mode, current_size_,false)); + begins_balls_.push_back(PrimParam(data_pos_.size(), mode, current_size_, false)); current_begin_ = &begins_balls_; } - else if (current_size_ > 2.0) + else if (current_size_ > 2.0f) { - begins_round_point_.push_back(PrimParam(data_pos_.size(), mode, current_size_,current_aa_)); + begins_round_point_.push_back(PrimParam(data_pos_.size(), mode, current_size_, current_aa_)); current_begin_ = &begins_round_point_; } else { - begins_point_.push_back(PrimParam(data_pos_.size(), mode, current_size_,false)); + begins_point_.push_back(PrimParam(data_pos_.size(), mode, current_size_, false)); current_begin_ = &begins_point_; } break; case GL_LINES: case GL_LINE_STRIP: case GL_LINE_LOOP: - if (current_size_ > 1.0) + if (current_size_ > 1.0f) { - begins_bold_line_.push_back(PrimParam(data_pos_.size(), mode, current_size_,current_aa_)); + begins_bold_line_.push_back(PrimParam(data_pos_.size(), mode, current_size_, current_aa_)); current_begin_ = &begins_bold_line_; } else { - begins_line_.push_back(PrimParam(data_pos_.size(), mode, 1.0,current_aa_)); + begins_line_.push_back(PrimParam(data_pos_.size(), mode, 1.0f, current_aa_)); current_begin_ = &begins_line_; } break; default: - begins_face_.push_back(PrimParam(data_pos_.size(), mode, 1.0f,false)); + begins_face_.push_back(PrimParam(data_pos_.size(), mode, 1.0f, false)); current_begin_ = &begins_face_; break; } - } -void Drawer::end() +void DisplayListDrawer::end() { current_begin_->back().nb = uint32(data_pos_.size() - current_begin_->back().begin); } - -void Drawer::vertex3f(float32 x, float32 y, float32 z) +void DisplayListDrawer::vertex3ff(float32 x, float32 y, float32 z) { if (data_pos_.size() == data_col_.size()) { @@ -169,37 +116,34 @@ void Drawer::vertex3f(float32 x, float32 y, float32 z) else data_col_.push_back( data_col_.back()); } - data_pos_.push_back(Vec3f{x,y,z}); + data_pos_.push_back(Vec3f{x, y, z}); } - -void Drawer::color3f(float32 r, float32 g, float32 b) +void DisplayListDrawer::color3ff(float32 r, float32 g, float32 b) { if (data_pos_.size() == data_col_.size()) - data_col_.push_back(Vec3f{r,g,b}); + data_col_.push_back(Vec3f{r, g, b}); else - data_col_.back() = Vec3f{r,g,b}; + data_col_.back() = Vec3f{r, g, b}; } - -void Drawer::end_list() +void DisplayListDrawer::end_list() { uint32 nb_elts = uint32(data_pos_.size()); if (nb_elts == 0) return; - vbo_pos_->allocate(nb_elts,3); + vbo_pos_->allocate(nb_elts, 3); float32* ptr = vbo_pos_->lock_pointer(); - std::memcpy(ptr,data_pos_[0].data(),nb_elts*12); + std::memcpy(ptr, data_pos_[0].data(), nb_elts*12); vbo_pos_->release_pointer(); - vbo_col_->allocate(nb_elts,3); + vbo_col_->allocate(nb_elts ,3); ptr = vbo_col_->lock_pointer(); - std::memcpy(ptr,data_col_[0].data(),nb_elts*12); + std::memcpy(ptr, data_col_[0].data(), nb_elts*12); vbo_col_->release_pointer(); - // free memory data_pos_.clear(); data_pos_.shrink_to_fit(); @@ -207,112 +151,207 @@ void Drawer::end_list() data_col_.shrink_to_fit(); } -void Drawer::call_list(const QMatrix4x4& projection, const QMatrix4x4& modelview) +//void DisplayListDrawer::call_list(const QMatrix4x4& projection, const QMatrix4x4& modelview, QOpenGLFunctions_3_3_Core* ogl33) +//{ + +// //classic rendering +// if (!begins_point_.empty() || !begins_line_.empty() || !begins_face_.empty()) +// { +// param_cpv_->bind(projection, modelview); + +// for (auto& pp : begins_point_) +// { +// ogl33->glPointSize(pp.width); +// ogl33->glDrawArrays(pp.mode, pp.begin, pp.nb); +// } + +// for (auto& pp : begins_line_) +// ogl33->glDrawArrays(pp.mode, pp.begin, pp.nb); + +// for (auto& pp : begins_face_) +// ogl33->glDrawArrays(pp.mode, pp.begin, pp.nb); + +// param_cpv_->release(); +// } + +// // balls +// if (!begins_balls_.empty()) +// { +// param_ps_->bind(projection,modelview); + +// for (auto& pp : begins_balls_) +// { +// ShaderPointSpriteColor* shader_ps_ = static_cast(param_ps_->get_shader()); +// shader_ps_->set_size(pp.width); +// ogl33->glDrawArrays(pp.mode, pp.begin, pp.nb); +// } +// param_ps_->release(); +// } + +// // round points +// if (!begins_round_point_.empty()) +// { +// param_rp_->bind(projection, modelview); + +// for (auto& pp : begins_round_point_) +// { +// if (pp.aa) +// { +// ogl33->glEnable(GL_BLEND); +// ogl33->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +// } +// ShaderRoundPointColor* shader_rp_ = static_cast(param_rp_->get_shader()); +// shader_rp_->set_size(pp.width); +// ogl33->glDrawArrays(pp.mode, pp.begin, pp.nb); + +// if (pp.aa) +// ogl33->glDisable(GL_BLEND); +// } +// param_rp_->release(); +// } + +// // bold lines +// if (!begins_bold_line_.empty()) +// { +// param_bl_->bind(projection, modelview); + +// for (auto& pp : begins_bold_line_) +// { +// ShaderBoldLineColor* shader_bl_ = static_cast(param_bl_->get_shader()); +// shader_bl_->set_width(pp.width); +// shader_bl_->set_color(QColor(255, 255, 0)); + +// if (pp.aa) +// { +// ogl33->glEnable(GL_BLEND); +// ogl33->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +// } + +// ogl33->glDrawArrays(pp.mode, pp.begin, pp.nb); + +// if (pp.aa) +// ogl33->glDisable(GL_BLEND); +// } + +// param_bl_->release(); +// } +//} + +DisplayListDrawer::Renderer::Renderer(DisplayListDrawer* dr) : + drawer_data_(dr) { + param_cpv_ = ShaderColorPerVertex::generate_param(); + param_bl_ = ShaderBoldLineColor::generate_param(); + param_rp_ = ShaderRoundPointColor::generate_param(); + param_ps_ = ShaderPointSpriteColor::generate_param(); + + param_cpv_->set_all_vbos(dr->vbo_pos_.get(), dr->vbo_col_.get()); + param_bl_->set_all_vbos(dr->vbo_pos_.get(), dr->vbo_col_.get()); + param_rp_->set_all_vbos(dr->vbo_pos_.get(), dr->vbo_col_.get()); + param_ps_->set_all_vbos(dr->vbo_pos_.get(), dr->vbo_col_.get()); +} +DisplayListDrawer::Renderer::~Renderer() +{ + param_cpv_.reset(); + param_bl_.reset(); + param_rp_.reset(); + param_ps_.reset(); +} + +void DisplayListDrawer::Renderer::draw(const QMatrix4x4& projection, const QMatrix4x4& modelview, QOpenGLFunctions_3_3_Core* ogl33) +{ //classic rendering - if (!begins_point_.empty() && !begins_line_.empty() && !begins_face_.empty()) + if (! drawer_data_->begins_point_.empty() || ! drawer_data_->begins_line_.empty() || ! drawer_data_->begins_face_.empty()) { - shader_cpv_->bind(); - shader_cpv_->set_matrices(projection,modelview); - shader_cpv_->bind_vao(vao_cpv_); + param_cpv_->bind(projection, modelview); - for (auto& pp : begins_point_) + for (auto& pp : drawer_data_->begins_point_) { - ogl33_->glPointSize(pp.width); - ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); + ogl33->glPointSize(pp.width); + ogl33->glDrawArrays(pp.mode, pp.begin, pp.nb); } - for (auto& pp : begins_line_) - { - ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); - } + for (auto& pp : drawer_data_->begins_line_) + ogl33->glDrawArrays(pp.mode, pp.begin, pp.nb); - for (auto& pp : begins_face_) - { - ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); - } + for (auto& pp : drawer_data_->begins_face_) + ogl33->glDrawArrays(pp.mode, pp.begin, pp.nb); - shader_cpv_->release_vao(vao_cpv_); - shader_cpv_->release(); + param_cpv_->release(); } // balls - if (!begins_balls_.empty()) + if (! drawer_data_->begins_balls_.empty()) { - shader_ps_->bind(); - shader_ps_->set_matrices(projection,modelview); - shader_ps_->bind_vao(vao_ps_); + param_ps_->bind(projection, modelview); - for (auto& pp : begins_balls_) + for (auto& pp : drawer_data_->begins_balls_) { + // get direct access to the shader to modify parameters while keeping the original param binded + ShaderPointSpriteColor* shader_ps_ = static_cast(param_ps_->get_shader()); shader_ps_->set_size(pp.width); - ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); + + ogl33->glDrawArrays(pp.mode, pp.begin, pp.nb); } - shader_ps_->release_vao(vao_ps_); - shader_ps_->release(); + + param_ps_->release(); } // round points - if (!begins_round_point_.empty()) + if (! drawer_data_->begins_round_point_.empty()) { - shader_rp_->bind(); - shader_rp_->set_matrices(projection,modelview); - shader_rp_->bind_vao(vao_rp_); + param_rp_->bind(projection, modelview); - for (auto& pp : begins_round_point_) + for (auto& pp : drawer_data_->begins_round_point_) { + // get direct access to the shader to modify parameters while keeping the original param binded + ShaderRoundPointColor* shader_rp_ = static_cast(param_rp_->get_shader()); + shader_rp_->set_size(pp.width); + if (pp.aa) { - ogl33_->glEnable(GL_BLEND); - ogl33_->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + ogl33->glEnable(GL_BLEND); + ogl33->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - shader_rp_->set_width(pp.width); - ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); + ogl33->glDrawArrays(pp.mode, pp.begin, pp.nb); if (pp.aa) - ogl33_->glDisable(GL_BLEND); - + ogl33->glDisable(GL_BLEND); } - shader_rp_->release_vao(vao_rp_); - shader_rp_->release(); + + param_rp_->release(); } // bold lines - if (!begins_bold_line_.empty()) + if (! drawer_data_->begins_bold_line_.empty()) { - shader_bl_->bind(); - shader_bl_->set_matrices(projection,modelview); - shader_bl_->bind_vao(vao_bl_); + param_bl_->bind(projection, modelview); - for (auto& pp : begins_bold_line_) + for (auto& pp : drawer_data_->begins_bold_line_) { + // get direct access to the shader to modify parameters while keeping the original param binded + ShaderBoldLineColor* shader_bl_ = static_cast(param_bl_->get_shader()); shader_bl_->set_width(pp.width); - shader_bl_->set_color(QColor(255,255,0)); + shader_bl_->set_color(QColor(255, 255, 0)); if (pp.aa) { - ogl33_->glEnable(GL_BLEND); - ogl33_->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + ogl33->glEnable(GL_BLEND); + ogl33->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); + ogl33->glDrawArrays(pp.mode, pp.begin, pp.nb); if (pp.aa) - ogl33_->glDisable(GL_BLEND); - + ogl33->glDisable(GL_BLEND); } - shader_bl_->release_vao(vao_bl_); - shader_bl_->release(); + param_bl_->release(); } - } - - - } // namespace rendering } // namespace cgogn diff --git a/cgogn/rendering/drawer.h b/cgogn/rendering/drawer.h index 6566422e..c1f85662 100644 --- a/cgogn/rendering/drawer.h +++ b/cgogn/rendering/drawer.h @@ -21,17 +21,18 @@ * * *******************************************************************************/ -#ifndef RENDERING_DRAWER_H_ -#define RENDERING_DRAWER_H_ +#ifndef CGOGN_RENDERING_DRAWER_H_ +#define CGOGN_RENDERING_DRAWER_H_ -#include -#include -#include -#include -#include +#include + +#include +#include +#include +#include +#include +#include -#include -#include #include namespace cgogn @@ -39,9 +40,30 @@ namespace cgogn namespace rendering { - - -class CGOGN_RENDERING_API Drawer +/** + * @brief DisplayListDrawer revival of old GL display-list + * + * Typical usage: + * + * std::unique_ptr drawer_; // can be shared between contexts + * std::unique_ptr drawer_rend_; // one by context, + * + * init: + * drawer_ = cgogn::make_unique(); + * drawer_rend_ = drawer_->generate_renderer(); // don't worry automatically deleted when finished + * drawer_->new_list(); + * drawer_->line_width(2.0); + * drawer_->begin(GL_LINE_LOOP); // or GL_POINTS, GL_LINES, GL_TRIANGLES + * drawer_->color3f(1.0,0.0,0.0); + * drawer_->vertex3f(0,0,0); + * drawer_->color3f(0.0,1.0,1.0); + * .... + * drawer_->end(); + * + * draw: + * drawer_rend_->draw(proj,view,this); + */ +class CGOGN_RENDERING_API DisplayListDrawer { struct PrimParam { @@ -50,58 +72,86 @@ class CGOGN_RENDERING_API Drawer float32 width; uint32 nb; bool aa; - PrimParam(std::size_t b, GLenum m, float32 w, bool a) : begin(uint32(b)), mode(m), width(w), nb(0), aa(a){} + + PrimParam(std::size_t b, GLenum m, float32 w, bool a) : + begin(uint32(b)), mode(m), width(w), nb(0), aa(a) + {} }; - using Vec3f = std::array; + using Vec3f = std::array; protected: - static ShaderColorPerVertex* shader_cpv_; - static ShaderBoldLine* shader_bl_; - static ShaderRoundPoint* shader_rp_; - static ShaderPointSprite* shader_ps_; - static int32 nb_instances_; - - VBO* vbo_pos_; - VBO* vbo_col_; + std::unique_ptr vbo_pos_; + std::unique_ptr vbo_col_; + // temporary (between begin()/end()) data storage std::vector data_pos_; std::vector data_col_; + // list of primitive call (of each kind) std::vector begins_point_; std::vector begins_round_point_; std::vector begins_balls_; - std::vector begins_line_; std::vector begins_bold_line_; std::vector begins_face_; std::vector* current_begin_; - uint32 vao_cpv_; - uint32 vao_bl_; - uint32 vao_rp_; - uint32 vao_ps_; - float32 current_size_; bool current_aa_; bool current_ball_; - QOpenGLFunctions_3_3_Core* ogl33_; - public: - using Self = Drawer; + + class CGOGN_RENDERING_API Renderer + { + friend class DisplayListDrawer; + std::unique_ptr param_cpv_; + std::unique_ptr param_bl_; + std::unique_ptr param_rp_; + std::unique_ptr param_ps_; + DisplayListDrawer* drawer_data_; + Renderer(DisplayListDrawer* dr); + public: + ~Renderer(); + + /** + * draw the compiled drawing list + * @param projection projection matrix + * @param modelview modelview matrix + * @param a pointer compatible with QOpenGLFunctions_3_3_Core* (QOGLViewer) + */ + void draw(const QMatrix4x4& projection, const QMatrix4x4& modelview, QOpenGLFunctions_3_3_Core* ogl33); + + }; + + using Self = DisplayListDrawer; + /** * constructor, init all buffers (data and OpenGL) and shader * @Warning need OpenGL context */ - Drawer(QOpenGLFunctions_3_3_Core* ogl33); + DisplayListDrawer(); + /** * release buffers and shader */ - ~Drawer(); - CGOGN_NOT_COPYABLE_NOR_MOVABLE(Drawer); + ~DisplayListDrawer(); + + /** + * @brief generate a renderer (one per context) + * @return pointer on renderer + */ + inline std::unique_ptr generate_renderer() + { + return std::unique_ptr(new Renderer(this)); + } + + + CGOGN_NOT_COPYABLE_NOR_MOVABLE(DisplayListDrawer); + /** * init the data structure @@ -125,61 +175,70 @@ class CGOGN_RENDERING_API Drawer */ void end_list(); + void vertex3ff(float32 x, float32 y, float32 z); + /** - * use as glVertex3f - */ - void vertex3f(float32 x, float32 y, float32 z); + * use as glVertex3f + */ + template + inline void vertex3f(SCAL x, SCAL y, SCAL z) + { + static_assert(std::is_arithmetic::value, "scalar value only allowed for vertex3"); + vertex3ff(float32(x), float32(y), float32(z)); + } + + + void color3ff(float32 r, float32 g, float32 b); /** - * use as glColor3f - */ - void color3f(float32 r, float32 g, float32 b); + * use as glColor3f + */ + template + inline void color3f(SCAL x, SCAL y, SCAL z) + { + static_assert(std::is_arithmetic::value, "scalar value only allowed for vertex3"); + color3ff(float32(x), float32(y), float32(z)); + } - inline void vertex3fv(const std::array& xyz) + inline void vertex3fv(const std::array& xyz) { - vertex3f(xyz[0],xyz[1],xyz[2]); + vertex3ff(xyz[0], xyz[1], xyz[2]); } - inline void color3fv(const std::array& rgb) + inline void color3fv(const std::array& rgb) { - color3f(rgb[0],rgb[1],rgb[2]); + color3ff(rgb[0], rgb[1], rgb[2]); } template inline void vertex3fv(SCAL* xyz) { - vertex3f(float32(xyz[0]),float32(xyz[1]),float32(xyz[2])); + static_assert(std::is_arithmetic::value, "scalar vector only allowed for vertex3"); + vertex3ff(float32(xyz[0]), float32(xyz[1]), float32(xyz[2])); } template inline void color3fv(SCAL* rgb) { - color3f(float32(rgb[0]),float32(rgb[1]),float32(rgb[2])); + static_assert(std::is_arithmetic::value, "scalar vector only allowed for vertex3"); + color3ff(float32(rgb[0]), float32(rgb[1]), float32(rgb[2])); } template inline void vertex3fv(const VEC3& xyz) { - vertex3f(float32(xyz[0]),float32(xyz[1]),float32(xyz[2])); + vertex3f(float32(xyz[0]), float32(xyz[1]), float32(xyz[2])); } template inline void color3fv(const VEC3& rgb) { - color3f(float32(rgb[0]),float32(rgb[1]),float32(rgb[2])); + color3f(float32(rgb[0]), float32(rgb[1]), float32(rgb[2])); } - - /** - * use as a glCallList (draw the compiled drawing list) - * @param projection projection matrix - * @param modelview modelview matrix - */ - void call_list(const QMatrix4x4& projection, const QMatrix4x4& modelview); - /** - * usr as glPointSize + * use as glPointSize */ inline void point_size(float32 ps) { @@ -188,6 +247,9 @@ class CGOGN_RENDERING_API Drawer current_ball_ = false; } + /** + * use as glPointSize with use of anti-aliasing (alpha blending) + */ inline void point_size_aa(float32 ps) { current_aa_ = true; @@ -195,6 +257,9 @@ class CGOGN_RENDERING_API Drawer current_ball_ = false; } + /** + * use as glPointSize for shaded ball rendering + */ inline void ball_size(float32 ps) { current_ball_ = true; @@ -202,9 +267,8 @@ class CGOGN_RENDERING_API Drawer current_size_ = ps; } - /** - * usr as glLineWidth + * use as glLineWidth */ inline void line_width(float32 lw) { @@ -212,19 +276,19 @@ class CGOGN_RENDERING_API Drawer current_size_ = lw; } + /** + * use as glLineWidth with use of anti-aliasing (alpha blending) + */ + inline void line_width_aa(float32 lw) { current_aa_ = true; current_size_ = 2.0*lw; } - - }; - - } // namespace rendering } // namespace cgogn -#endif // RENDERING_DRAWER_H_ +#endif // CGOGN_RENDERING_DRAWER_H_ diff --git a/cgogn/rendering/examples/CMakeLists.txt b/cgogn/rendering/examples/CMakeLists.txt index 44bc8f1e..4f56cbe8 100644 --- a/cgogn/rendering/examples/CMakeLists.txt +++ b/cgogn/rendering/examples/CMakeLists.txt @@ -4,6 +4,12 @@ project(cgogn_rendering_examples LANGUAGES CXX ) +find_package(cgogn_core REQUIRED) +find_package(cgogn_geometry REQUIRED) +find_package(cgogn_io REQUIRED) +find_package(cgogn_rendering REQUIRED) +find_package(QOGLViewer REQUIRED) + set(CMAKE_AUTOMOC ON) @@ -13,22 +19,19 @@ add_definitions("-DCGOGN_TEST_MESHES_PATH=${CGOGN_TEST_MESHES_PATH}") add_executable(simple_viewer simple_viewer.cpp) -target_link_libraries(simple_viewer cgogn_core cgogn_io cgogn_rendering QOGLViewer) +target_link_libraries(simple_viewer ${cgogn_core_LIBRARIES} ${cgogn_io_LIBRARIES} ${cgogn_rendering_LIBRARIES} ${QOGLViewer_LIBRARIES}) add_executable(viewer_per_face viewer_per_face.cpp) -target_link_libraries(viewer_per_face cgogn_core cgogn_io cgogn_rendering QOGLViewer) +target_link_libraries(viewer_per_face ${cgogn_core_LIBRARIES} ${cgogn_io_LIBRARIES} ${cgogn_rendering_LIBRARIES} ${QOGLViewer_LIBRARIES}) add_executable(viewer_topo viewer_topo.cpp) -target_link_libraries(viewer_topo cgogn_core cgogn_io cgogn_rendering QOGLViewer) +target_link_libraries(viewer_topo ${cgogn_core_LIBRARIES} ${cgogn_io_LIBRARIES} ${cgogn_rendering_LIBRARIES} ${QOGLViewer_LIBRARIES}) add_executable(drawing drawing.cpp) -target_link_libraries(drawing cgogn_rendering QOGLViewer) +target_link_libraries(drawing ${cgogn_rendering_LIBRARIES} ${QOGLViewer_LIBRARIES}) add_executable(picking_viewer picking_viewer.cpp) -target_link_libraries(picking_viewer cgogn_core cgogn_io cgogn_rendering QOGLViewer) - +target_link_libraries(picking_viewer ${cgogn_core_LIBRARIES} ${cgogn_io_LIBRARIES} ${cgogn_rendering_LIBRARIES} ${QOGLViewer_LIBRARIES}) add_executable(viewer_topo3 viewer_topo3.cpp) -target_link_libraries(viewer_topo3 cgogn_core cgogn_io cgogn_rendering QOGLViewer) - - +target_link_libraries(viewer_topo3 ${cgogn_core_LIBRARIES} ${cgogn_io_LIBRARIES} ${cgogn_rendering_LIBRARIES} ${QOGLViewer_LIBRARIES}) diff --git a/cgogn/rendering/examples/drawing.cpp b/cgogn/rendering/examples/drawing.cpp index a77d5178..6fe108e4 100644 --- a/cgogn/rendering/examples/drawing.cpp +++ b/cgogn/rendering/examples/drawing.cpp @@ -27,7 +27,9 @@ #include #include -#include +#include + +#include #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) @@ -38,17 +40,26 @@ class Drawing : public QOGLViewer { public: Drawing(); - Drawing(const Drawing&) = delete; - Drawing& operator=(const Drawing&) = delete; + Drawing(Drawing* ptr); + CGOGN_NOT_COPYABLE_NOR_MOVABLE(Drawing); virtual void draw(); virtual void init(); virtual void closeEvent(QCloseEvent *e); virtual ~Drawing(); -private: - cgogn::rendering::Drawer* drawer_; - cgogn::rendering::Drawer* drawer2_; +//private: + std::shared_ptr drawer_; + std::shared_ptr drawer2_; + std::unique_ptr drawer_rend_; + std::unique_ptr drawer2_rend_; + + std::shared_ptr wp_; + std::shared_ptr button_; + std::unique_ptr wp_rend_; + std::unique_ptr button_rend_; + + Drawing* m_first; }; @@ -58,25 +69,59 @@ Drawing::~Drawing() void Drawing::closeEvent(QCloseEvent*) { - delete drawer_; - delete drawer2_; + this->makeCurrent(); + + drawer_rend_.reset(); + drawer2_rend_.reset(); + wp_rend_.reset(); + button_rend_.reset(); + + drawer_.reset(); + drawer2_.reset(); + wp_.reset(); + button_.reset(); } Drawing::Drawing() : drawer_(nullptr), - drawer2_(nullptr) + drawer2_(nullptr), + drawer_rend_(nullptr), + drawer2_rend_(nullptr), + wp_(nullptr), + button_(nullptr), + wp_rend_(nullptr), + button_rend_(nullptr), + m_first(nullptr) +{ + m_first = this; +} + +Drawing::Drawing(Drawing* ptr) : + QOGLViewer(ptr), + drawer_(nullptr), + drawer2_(nullptr), + drawer_rend_(nullptr), + drawer2_rend_(nullptr), + wp_(nullptr), + button_(nullptr), + wp_rend_(nullptr), + button_rend_(nullptr), + m_first(ptr) {} void Drawing::draw() { + wp_rend_->draw(this); + button_rend_->draw(this); + QMatrix4x4 proj; QMatrix4x4 view; camera()->getProjectionMatrix(proj); camera()->getModelViewMatrix(view); - drawer_->call_list(proj,view); - drawer2_->call_list(proj,view); + drawer_rend_->draw(proj,view,this); + drawer2_rend_->draw(proj,view,this); } void Drawing::init() @@ -84,31 +129,57 @@ void Drawing::init() setSceneRadius(5.0); setSceneCenter(qoglviewer::Vec(0.0,0.0,0.0)); showEntireScene(); - glClearColor(0.1f,0.1f,0.3f,0.0f); + this->makeCurrent(); + + if (m_first!=this) + { + drawer_ = m_first->drawer_; + drawer2_ = m_first->drawer2_; + wp_ = m_first->wp_; + button_ = m_first->button_; + + drawer_rend_ = drawer_->generate_renderer(); + drawer2_rend_ = drawer2_->generate_renderer(); + wp_rend_ = wp_->generate_renderer(); + button_rend_ = button_->generate_renderer(); + return; + } + + wp_ = std::make_shared(QImage(QString(DEFAULT_MESH_PATH) + QString("../images/cgogn2.png"))); + button_ = std::make_shared(QImage(QString(DEFAULT_MESH_PATH) + QString("../images/igg.png"))); +// button_->set_local_position(this->width(),this->height(),10,10,50,50); + button_->set_local_position(0.1f,0.1f,0.2f,0.2f); + + wp_rend_ = wp_->generate_renderer(); + button_rend_ = button_->generate_renderer(); + // drawer for simple old-school g1 rendering - drawer_ = new cgogn::rendering::Drawer(this); + drawer_ = std::make_shared(); + drawer_rend_ = drawer_->generate_renderer(); drawer_->new_list(); drawer_->line_width(2.0); drawer_->begin(GL_LINE_LOOP); drawer_->color3f(1.0,0.0,0.0); - drawer_->vertex3f(0,0,0); + drawer_->vertex3f(0.0,0.0,0.0); drawer_->color3f(0.0,1.0,1.0); drawer_->vertex3f(1,0,0); drawer_->color3f(1.0,0.0,1.0); - drawer_->vertex3f(1,1,0); + drawer_->vertex3f(1.0f,1.0f,0.0f); drawer_->color3f(1.0,1.0,0.0); drawer_->vertex3f(0,1,0); drawer_->end(); -// drawer_->point_size(10.0); drawer_->line_width_aa(3.0); drawer_->begin(GL_LINES); - drawer_->color3f(1.0,1.0,1.0); - drawer_->vertex3fv(Vec3(-1,1,0)); - drawer_->vertex3fv(Vec3(-1.2,0,0)); - drawer_->vertex3fv(Vec3(-2,0,0)); - drawer_->vertex3fv(Vec3(-2.2,3,0)); + drawer_->color3f(0.0,0.8,0.0); + drawer_->vertex3fv(Vec3(-1,2,0)); + drawer_->color3f(0.0,0.0,0.8); + drawer_->vertex3fv(Vec3(-1.3,0,0)); + drawer_->color3f(0.0,0.0,0.8); + drawer_->vertex3fv(Vec3(-2,1,0)); + drawer_->color3f(0.8,0.0,0.0); + drawer_->vertex3fv(Vec3(-2.3,3,0)); drawer_->end(); drawer_->begin(GL_TRIANGLES); @@ -144,7 +215,8 @@ void Drawing::init() drawer_->end(); drawer_->end_list(); - drawer2_ = new cgogn::rendering::Drawer(this); + drawer2_ = std::make_shared(); + drawer2_rend_ = drawer2_->generate_renderer(); drawer2_->new_list(); drawer2_->point_size_aa(5.0); drawer2_->begin(GL_POINTS); @@ -174,15 +246,28 @@ void Drawing::init() int main(int argc, char** argv) { + qoglviewer::init_ogl_context(); + QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts); QApplication application(argc, argv); - qoglviewer::init_ogl_context(); + // Instantiate the viewer. - Drawing viewer; - viewer.setWindowTitle("Drawing"); - viewer.show(); + + std::unique_ptr viewer = cgogn::make_unique(); + viewer->setWindowTitle("Drawing"); + viewer->show(); + + std::unique_ptr viewer2 = cgogn::make_unique(viewer.get()); + viewer2->setWindowTitle("Drawing2"); + viewer2->show(); + +// cgogn_log_info("are context shared ?") << std::boolalpha << QOpenGLContext::areSharing(viewer2->context(),viewer->context()); // Run main loop. - return application.exec(); + const int ret = application.exec(); + + viewer.reset(); + viewer2.reset(); + return ret; } diff --git a/cgogn/rendering/examples/picking_viewer.cpp b/cgogn/rendering/examples/picking_viewer.cpp index 3927313d..b7e5fab5 100644 --- a/cgogn/rendering/examples/picking_viewer.cpp +++ b/cgogn/rendering/examples/picking_viewer.cpp @@ -29,18 +29,18 @@ #include #include -#include +#include -#include +#include -#include +#include -#include -#include -#include -#include +#include +#include +#include +#include -#include +#include #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) @@ -51,15 +51,14 @@ using Map2 = cgogn::CMap2; using Vec3 = cgogn::geometry::Vec_T>; template -using VertexAttributeHandler = Map2::VertexAttributeHandler; +using VertexAttribute = Map2::VertexAttribute; class Viewer : public QOGLViewer { public: Viewer(); - Viewer(const Viewer&) = delete; - Viewer& operator=(const Viewer&) = delete; + CGOGN_NOT_COPYABLE_NOR_MOVABLE(Viewer); virtual void draw(); virtual void init(); @@ -75,23 +74,24 @@ class Viewer : public QOGLViewer private: void rayClick(QMouseEvent* event, qoglviewer::Vec& P, qoglviewer::Vec& Q); - - QRect viewport_; QMatrix4x4 proj_; QMatrix4x4 view_; Map2 map_; - VertexAttributeHandler vertex_position_; - cgogn::geometry::BoundingBox bb_; + VertexAttribute vertex_position_; + + cgogn::geometry::AABB bb_; + + std::unique_ptr render_; - cgogn::rendering::MapRender* render_; - cgogn::rendering::VBO* vbo_pos_; + std::unique_ptr vbo_pos_; - cgogn::rendering::ShaderFlat* shader2_; + std::unique_ptr param_flat_; - cgogn::rendering::Drawer* drawer_; + std::unique_ptr drawer_; + std::unique_ptr drawer_rend_; int32 cell_picking; }; @@ -108,7 +108,7 @@ void Viewer::import(const std::string& surfaceMesh) vertex_position_ = map_.get_attribute("position"); - cgogn::geometry::compute_bounding_box(vertex_position_, bb_); + cgogn::geometry::compute_AABB(vertex_position_, bb_); setSceneRadius(bb_.diag_size()/2.0); Vec3 center = bb_.center(); @@ -117,11 +117,7 @@ void Viewer::import(const std::string& surfaceMesh) } Viewer::~Viewer() -{ - delete render_; - delete vbo_pos_; - delete shader2_; -} +{} Viewer::Viewer() : map_(), @@ -129,7 +125,6 @@ Viewer::Viewer() : bb_(), render_(nullptr), vbo_pos_(nullptr), - shader2_(nullptr), drawer_(nullptr), cell_picking(0) {} @@ -142,50 +137,42 @@ void Viewer::draw() glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1.0f, 1.0f); - shader2_->bind(); - shader2_->set_matrices(proj_,view_); - shader2_->bind_vao(0); + param_flat_->bind(proj_, view_); render_->draw(cgogn::rendering::TRIANGLES); - shader2_->release_vao(0); - shader2_->release(); + param_flat_->release(); glDisable(GL_POLYGON_OFFSET_FILL); - drawer_->call_list(proj_,view_); - + drawer_rend_->draw(proj_, view_, this); } void Viewer::init() { - glClearColor(0.1f,0.1f,0.3f,0.0f); + glClearColor(0.1f, 0.1f, 0.3f, 0.0f); - vbo_pos_ = new cgogn::rendering::VBO(3); - cgogn::rendering::update_vbo(vertex_position_, *vbo_pos_); - render_ = new cgogn::rendering::MapRender(); + vbo_pos_ = cgogn::make_unique(3); + cgogn::rendering::update_vbo(vertex_position_, vbo_pos_.get()); - render_->init_primitives(map_, cgogn::rendering::TRIANGLES, vertex_position_); + render_ = cgogn::make_unique(); + render_->init_primitives(map_, cgogn::rendering::TRIANGLES, &vertex_position_); - shader2_ = new cgogn::rendering::ShaderFlat; - shader2_->add_vao(); - shader2_->set_vao(0, vbo_pos_); + param_flat_ = cgogn::rendering::ShaderFlat::generate_param(); - shader2_->bind(); - shader2_->set_front_color(QColor(0,200,0)); - shader2_->set_back_color(QColor(0,0,200)); - shader2_->set_ambiant_color(QColor(5,5,5)); - shader2_->release(); + param_flat_->set_position_vbo(vbo_pos_.get()); + param_flat_->front_color_ = QColor(0,200,0); + param_flat_->back_color_ = QColor(200,0,0); + param_flat_->ambiant_color_ = QColor(5,5,5); - drawer_ = new cgogn::rendering::Drawer(this); + drawer_ = cgogn::make_unique(); + drawer_rend_ = drawer_->generate_renderer(); } - void Viewer::rayClick(QMouseEvent* event, qoglviewer::Vec& P, qoglviewer::Vec& Q) { - P = camera()->unprojectedCoordinatesOf(qoglviewer::Vec(event->x(),event->y(),0.0)); - Q = camera()->unprojectedCoordinatesOf(qoglviewer::Vec(event->x(),event->y(),1.0)); + P = camera()->unprojectedCoordinatesOf(qoglviewer::Vec(event->x(), event->y(), 0.0)); + Q = camera()->unprojectedCoordinatesOf(qoglviewer::Vec(event->x(), event->y(), 1.0)); } - void Viewer::keyPressEvent(QKeyEvent *ev) { switch (ev->key()) @@ -252,11 +239,11 @@ void Viewer::mousePressEvent(QMouseEvent* event) drawer_->begin(GL_LINES); // closest face in red drawer_->color3f(1.0,0.0,0.0); - cgogn::rendering::add_edge_to_drawer(map_,selected[0],vertex_position_,drawer_); + cgogn::rendering::add_edge_to_drawer(map_,selected[0],vertex_position_,drawer_.get()); // others in yellow drawer_->color3f(1.0,1.0,0.0); for(uint32 i=1u;i(map_,selected[i],vertex_position_,drawer_); + cgogn::rendering::add_edge_to_drawer(map_,selected[i],vertex_position_,drawer_.get()); drawer_->end(); } } @@ -272,11 +259,11 @@ void Viewer::mousePressEvent(QMouseEvent* event) drawer_->begin(GL_LINES); // closest face in red drawer_->color3f(1.0,0.0,0.0); - cgogn::rendering::add_face_to_drawer(map_,selected[0],vertex_position_,drawer_); + cgogn::rendering::add_face_to_drawer(map_,selected[0],vertex_position_,drawer_.get()); // others in yellow drawer_->color3f(1.0,1.0,0.0); for(uint32 i=1u;i(map_,selected[i],vertex_position_,drawer_); + cgogn::rendering::add_face_to_drawer(map_,selected[i],vertex_position_,drawer_.get()); drawer_->end(); } } @@ -292,11 +279,11 @@ void Viewer::mousePressEvent(QMouseEvent* event) drawer_->begin(GL_LINES); // closest face in red drawer_->color3f(1.0,0.0,0.0); - cgogn::rendering::add_volume_to_drawer(map_,selected[0],vertex_position_,drawer_); + cgogn::rendering::add_volume_to_drawer(map_,selected[0],vertex_position_,drawer_.get()); // others in yellow drawer_->color3f(1.0,1.0,0.0); for(uint32 i=1u;i(map_,selected[i],vertex_position_,drawer_); + cgogn::rendering::add_volume_to_drawer(map_,selected[i],vertex_position_,drawer_.get()); drawer_->end(); } } diff --git a/cgogn/rendering/examples/simple_viewer.cpp b/cgogn/rendering/examples/simple_viewer.cpp index 8c410d37..a00ce91e 100644 --- a/cgogn/rendering/examples/simple_viewer.cpp +++ b/cgogn/rendering/examples/simple_viewer.cpp @@ -27,27 +27,27 @@ #include #include -#include +#include -#include +#include -#include -#include +#include +#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include -#include +#include -#include +#include -#include +#include #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) @@ -56,46 +56,48 @@ using Vec3 = Eigen::Vector3d; //using Vec3 = cgogn::geometry::Vec_T>; template -using VertexAttributeHandler = Map2::VertexAttributeHandler; +using VertexAttribute = Map2::VertexAttribute; class Viewer : public QOGLViewer { public: + Viewer(); - Viewer(const Viewer&) = delete; - Viewer& operator=(const Viewer&) = delete; + CGOGN_NOT_COPYABLE_NOR_MOVABLE(Viewer); virtual void draw(); virtual void init(); virtual void keyPressEvent(QKeyEvent *); - void import(const std::string& surfaceMesh); + void import(const std::string& surface_mesh); virtual ~Viewer(); virtual void closeEvent(QCloseEvent *e); private: + Map2 map_; - VertexAttributeHandler vertex_position_; - VertexAttributeHandler vertex_normal_; + VertexAttribute vertex_position_; + VertexAttribute vertex_normal_; - cgogn::geometry::BoundingBox bb_; + cgogn::geometry::AABB bb_; - cgogn::rendering::MapRender* render_; + std::unique_ptr render_; - cgogn::rendering::VBO* vbo_pos_; - cgogn::rendering::VBO* vbo_norm_; - cgogn::rendering::VBO* vbo_color_; - cgogn::rendering::VBO* vbo_sphere_sz_; + std::unique_ptr vbo_pos_; + std::unique_ptr vbo_norm_; + std::unique_ptr vbo_color_; + std::unique_ptr vbo_sphere_sz_; -// cgogn::rendering::ShaderSimpleColor* shader_vertex_; - cgogn::rendering::ShaderBoldLine* shader_edge_; - cgogn::rendering::ShaderFlat* shader_flat_; - cgogn::rendering::ShaderVectorPerVertex* shader_normal_; - cgogn::rendering::ShaderPhong* shader_phong_; - cgogn::rendering::ShaderPointSprite* shader_point_sprite_; + std::unique_ptr param_edge_; + std::unique_ptr param_flat_; + std::unique_ptr param_normal_; + std::unique_ptr param_phong_; + std::unique_ptr param_point_sprite_; - cgogn::rendering::Drawer* drawer_; + + std::unique_ptr drawer_; + std::unique_ptr drawer_rend_; bool phong_rendering_; bool flat_rendering_; @@ -103,7 +105,6 @@ class Viewer : public QOGLViewer bool edge_rendering_; bool normal_rendering_; bool bb_rendering_; - }; @@ -112,21 +113,27 @@ class Viewer : public QOGLViewer // -void Viewer::import(const std::string& surfaceMesh) +void Viewer::import(const std::string& surface_mesh) { - cgogn::io::import_surface(map_, surfaceMesh); + cgogn::io::import_surface(map_, surface_mesh); vertex_position_ = map_.get_attribute("position"); - vertex_normal_ = map_.add_attribute("normal"); if (!vertex_position_.is_valid()) { cgogn_log_error("Viewer::import") << "Missing attribute position. Aborting."; std::exit(EXIT_FAILURE); } + vertex_normal_ = map_.add_attribute("normal"); + +// testing merge method +// Map2 map2; +// cgogn::io::import_surface(map2, std::string(DEFAULT_MESH_PATH) + std::string("off/star_convex.off")); +// map_.merge(map2); + cgogn::geometry::compute_normal_vertices(map_, vertex_position_, vertex_normal_); - cgogn::geometry::compute_bounding_box(vertex_position_, bb_); + cgogn::geometry::compute_AABB(vertex_position_, bb_); setSceneRadius(bb_.diag_size()/2.0); Vec3 center = bb_.center(); setSceneCenter(qoglviewer::Vec(center[0], center[1], center[2])); @@ -138,17 +145,13 @@ Viewer::~Viewer() void Viewer::closeEvent(QCloseEvent*) { - delete render_; - delete vbo_pos_; - delete vbo_norm_; - delete vbo_color_; - delete vbo_sphere_sz_; - delete shader_edge_; - delete shader_flat_; - delete shader_normal_; - delete shader_phong_; - delete shader_point_sprite_; - delete drawer_; + render_.reset(); + vbo_pos_.reset(); + vbo_norm_.reset(); + vbo_color_.reset(); + vbo_sphere_sz_.reset(); + drawer_.reset(); + drawer_rend_.reset(); } Viewer::Viewer() : @@ -161,12 +164,8 @@ Viewer::Viewer() : vbo_norm_(nullptr), vbo_color_(nullptr), vbo_sphere_sz_(nullptr), - shader_edge_(nullptr), - shader_flat_(nullptr), - shader_normal_(nullptr), - shader_phong_(nullptr), - shader_point_sprite_(nullptr), drawer_(nullptr), + drawer_rend_(nullptr), phong_rendering_(true), flat_rendering_(false), vertices_rendering_(false), @@ -216,147 +215,109 @@ void Viewer::draw() glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1.0f, 2.0f); - if (flat_rendering_) { - shader_flat_->bind(); - shader_flat_->set_matrices(proj,view); -// shader_flat_->set_local_light_position(QVector3D(bb_.max()[0],bb_.max()[1],bb_.max()[2]), view); - shader_flat_->bind_vao(0); + param_flat_->bind(proj,view); render_->draw(cgogn::rendering::TRIANGLES); - shader_flat_->release_vao(0); - shader_flat_->release(); + param_flat_->release(); } if (phong_rendering_) { - shader_phong_->bind(); - shader_phong_->set_matrices(proj,view); - shader_phong_->bind_vao(0); + param_phong_->bind(proj,view); render_->draw(cgogn::rendering::TRIANGLES); - shader_phong_->release_vao(0); - shader_phong_->release(); + param_phong_->release(); } glDisable(GL_POLYGON_OFFSET_FILL); - if (vertices_rendering_) { - shader_point_sprite_->bind(); - shader_point_sprite_->set_matrices(proj,view); - shader_point_sprite_->bind_vao(0); + param_point_sprite_->bind(proj,view); render_->draw(cgogn::rendering::POINTS); - shader_point_sprite_->release_vao(0); - shader_point_sprite_->release(); - + param_point_sprite_->release(); } if (edge_rendering_) { - shader_edge_->bind(); - shader_edge_->set_matrices(proj,view); - shader_edge_->bind_vao(0); - shader_edge_->set_width(2.5f); + param_edge_->bind(proj,view); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); render_->draw(cgogn::rendering::LINES); glDisable(GL_BLEND); - shader_edge_->release_vao(0); - shader_edge_->release(); + param_edge_->release(); } if (normal_rendering_) { - shader_normal_->bind(); - shader_normal_->set_matrices(proj,view); - shader_normal_->bind_vao(0); + param_normal_->bind(proj,view); render_->draw(cgogn::rendering::POINTS); - shader_normal_->release_vao(0); - shader_normal_->release(); + param_normal_->release(); } if (bb_rendering_) - drawer_->call_list(proj,view); + drawer_rend_->draw(proj,view,this); } void Viewer::init() { glClearColor(0.1f,0.1f,0.3f,0.0f); - vbo_pos_ = new cgogn::rendering::VBO(3); - cgogn::rendering::update_vbo(vertex_position_, *vbo_pos_); + // create and fill VBO for positions + vbo_pos_ = cgogn::make_unique(3); + cgogn::rendering::update_vbo(vertex_position_, vbo_pos_.get()); - vbo_norm_ = new cgogn::rendering::VBO(3); - cgogn::rendering::update_vbo(vertex_normal_, *vbo_norm_); + // create and fill VBO for normals + vbo_norm_ = cgogn::make_unique(3); + cgogn::rendering::update_vbo(vertex_normal_, vbo_norm_.get()); // fill a color vbo with abs of normals - vbo_color_ = new cgogn::rendering::VBO(3); - cgogn::rendering::update_vbo(vertex_normal_, *vbo_color_,[] (const Vec3& n) -> std::array + vbo_color_ = cgogn::make_unique(3); + cgogn::rendering::update_vbo(vertex_normal_, vbo_color_.get(), [] (const Vec3& n) -> std::array { return {float(std::abs(n[0])), float(std::abs(n[1])), float(std::abs(n[2]))}; }); // fill a sphere size vbo - vbo_sphere_sz_ = new cgogn::rendering::VBO(1); - cgogn::rendering::update_vbo(vertex_normal_, *vbo_sphere_sz_,[&] (const Vec3& n) -> float + vbo_sphere_sz_ = cgogn::make_unique(1); + cgogn::rendering::update_vbo(vertex_normal_, vbo_sphere_sz_.get(), [&] (const Vec3& n) -> float { return bb_.diag_size()/1000.0 * (1.0 + 2.0*std::abs(n[2])); }); - - render_ = new cgogn::rendering::MapRender(); - - render_->init_primitives(map_, cgogn::rendering::POINTS, vertex_position_); - render_->init_primitives(map_, cgogn::rendering::LINES, vertex_position_); - render_->init_primitives(map_, cgogn::rendering::TRIANGLES, vertex_position_); - - shader_point_sprite_ = new cgogn::rendering::ShaderPointSprite(true,true); - shader_point_sprite_->add_vao(); - shader_point_sprite_->set_vao(0, vbo_pos_,vbo_color_,vbo_sphere_sz_); - shader_point_sprite_->bind(); - shader_point_sprite_->set_size(bb_.diag_size()/1000.0); - shader_point_sprite_->set_color(QColor(255,0,0)); - shader_point_sprite_->release(); - - - shader_edge_ = new cgogn::rendering::ShaderBoldLine() ; - shader_edge_->add_vao(); - shader_edge_->set_vao(0, vbo_pos_); - shader_edge_->bind(); - shader_edge_->set_color(QColor(255,255,0)); - shader_edge_->release(); - - shader_flat_ = new cgogn::rendering::ShaderFlat; - shader_flat_->add_vao(); - shader_flat_->set_vao(0, vbo_pos_); - shader_flat_->bind(); - shader_flat_->set_front_color(QColor(0,200,0)); - shader_flat_->set_back_color(QColor(0,0,200)); - shader_flat_->set_ambiant_color(QColor(5,5,5)); - shader_flat_->release(); - - shader_normal_ = new cgogn::rendering::ShaderVectorPerVertex; - shader_normal_->add_vao(); - shader_normal_->set_vao(0, vbo_pos_, vbo_norm_); - shader_normal_->bind(); - shader_normal_->set_color(QColor(200,0,200)); - shader_normal_->set_length(bb_.diag_size()/50); - shader_normal_->release(); - - - shader_phong_ = new cgogn::rendering::ShaderPhong(true); - shader_phong_->add_vao(); - shader_phong_->set_vao(0, vbo_pos_, vbo_norm_, vbo_color_); - shader_phong_->bind(); -// shader_phong_->set_ambiant_color(QColor(5,5,5)); -// shader_phong_->set_double_side(true); -// shader_phong_->set_specular_color(QColor(255,255,255)); -// shader_phong_->set_specular_coef(10.0); - shader_phong_->release(); - + // map rendering object (primitive creation & sending to GPU) + render_ = cgogn::make_unique(); + render_->init_primitives(map_, cgogn::rendering::POINTS); + render_->init_primitives(map_, cgogn::rendering::LINES); + render_->init_primitives(map_, cgogn::rendering::TRIANGLES, &vertex_position_); + + // generation of one parameter set (for this shader) : vbo + uniforms + param_point_sprite_ = cgogn::rendering::ShaderPointSpriteColorSize::generate_param(); + // set vbo param (see param::set_vbo signature) + param_point_sprite_->set_all_vbos(vbo_pos_.get(), vbo_color_.get(), vbo_sphere_sz_.get()); + // set uniforms data + + param_edge_ = cgogn::rendering::ShaderBoldLine::generate_param(); + param_edge_->set_position_vbo(vbo_pos_.get()); + param_edge_->color_ = QColor(255,255,0); + param_edge_->width_= 2.5f; + + param_flat_ = cgogn::rendering::ShaderFlat::generate_param(); + param_flat_->set_position_vbo(vbo_pos_.get()); + param_flat_->front_color_ = QColor(0,200,0); + param_flat_->back_color_ = QColor(0,0,200); + param_flat_->ambiant_color_ = QColor(5,5,5); + + param_normal_ = cgogn::rendering::ShaderVectorPerVertex::generate_param(); + param_normal_->set_all_vbos(vbo_pos_.get(), vbo_norm_.get()); + param_normal_->color_ = QColor(200,0,200); + param_normal_->length_ = bb_.diag_size()/50; + + param_phong_ = cgogn::rendering::ShaderPhongColor::generate_param(); + param_phong_->set_all_vbos(vbo_pos_.get(), vbo_norm_.get(), vbo_color_.get()); // drawer for simple old-school g1 rendering - drawer_ = new cgogn::rendering::Drawer(this); + drawer_ = cgogn::make_unique(); + drawer_rend_= drawer_->generate_renderer(); drawer_->new_list(); drawer_->line_width_aa(2.0); drawer_->begin(GL_LINE_LOOP); @@ -382,20 +343,19 @@ void Viewer::init() drawer_->vertex3f(bb_.max()[0],bb_.max()[1],bb_.max()[2]); drawer_->end(); drawer_->end_list(); - } int main(int argc, char** argv) { - std::string surfaceMesh; + std::string surface_mesh; if (argc < 2) { cgogn_log_info("simple_viewer") << "USAGE: " << argv[0] << " [filename]"; - surfaceMesh = std::string(DEFAULT_MESH_PATH) + std::string("off/aneurysm_3D.off"); - cgogn_log_info("simple_viewer") << "Using default mesh \"" << surfaceMesh << "\"."; + surface_mesh = std::string(DEFAULT_MESH_PATH) + std::string("off/aneurysm_3D.off"); + cgogn_log_info("simple_viewer") << "Using default mesh \"" << surface_mesh << "\"."; } else - surfaceMesh = std::string(argv[1]); + surface_mesh = std::string(argv[1]); QApplication application(argc, argv); qoglviewer::init_ogl_context(); @@ -403,7 +363,7 @@ int main(int argc, char** argv) // Instantiate the viewer. Viewer viewer; viewer.setWindowTitle("simpleViewer"); - viewer.import(surfaceMesh); + viewer.import(surface_mesh); viewer.show(); // Run main loop. diff --git a/cgogn/rendering/examples/viewer_per_face.cpp b/cgogn/rendering/examples/viewer_per_face.cpp index 154c5889..9d417a0c 100644 --- a/cgogn/rendering/examples/viewer_per_face.cpp +++ b/cgogn/rendering/examples/viewer_per_face.cpp @@ -27,18 +27,18 @@ #include #include -#include +#include -#include +#include -#include -#include +#include +#include -#include -//#include -#include -#include -#include +#include +//#include +#include +#include +#include #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) @@ -51,18 +51,17 @@ using Vec3 = Eigen::Vector3d; //using Vec3 = cgogn::geometry::Vec_T>; template -using VertexAttributeHandler = Map2::VertexAttributeHandler; +using VertexAttribute = Map2::VertexAttribute; template -using FaceAttributeHandler = Map2::FaceAttributeHandler; +using FaceAttribute = Map2::FaceAttribute; class Viewer : public QOGLViewer { public: Viewer(); - Viewer(const Viewer&) = delete; - Viewer& operator=(const Viewer&) = delete; + CGOGN_NOT_COPYABLE_NOR_MOVABLE(Viewer); virtual void draw(); virtual void init(); @@ -74,17 +73,17 @@ class Viewer : public QOGLViewer private: Map2 map_; - VertexAttributeHandler vertex_position_; - FaceAttributeHandler face_normal_; + VertexAttribute vertex_position_; + FaceAttribute face_normal_; - cgogn::geometry::BoundingBox bb_; + cgogn::geometry::AABB bb_; - cgogn::rendering::VBO* vbo_pos_; - cgogn::rendering::VBO* vbo_norm_; - cgogn::rendering::VBO* vbo_color_; + std::unique_ptr vbo_pos_; + std::unique_ptr vbo_norm_; + std::unique_ptr vbo_color_; - cgogn::rendering::ShaderFlat* shader_flat_; - cgogn::rendering::ShaderPhong* shader_phong_; + std::unique_ptr param_flat_; + std::unique_ptr param_phong_; bool phong_rendering_; bool flat_rendering_; @@ -104,7 +103,7 @@ void Viewer::import(const std::string& surfaceMesh) face_normal_ = map_.add_attribute("normal"); cgogn::geometry::compute_normal_faces(map_, vertex_position_, face_normal_); - cgogn::geometry::compute_bounding_box(vertex_position_, bb_); + cgogn::geometry::compute_AABB(vertex_position_, bb_); setSceneRadius(bb_.diag_size()/2.0); Vec3 center = bb_.center(); @@ -117,11 +116,9 @@ Viewer::~Viewer() void Viewer::closeEvent(QCloseEvent*) { - delete vbo_pos_; - delete vbo_norm_; - delete vbo_color_; - delete shader_flat_; - delete shader_phong_; + vbo_pos_.reset(); + vbo_norm_.reset(); + vbo_color_.reset(); } Viewer::Viewer() : @@ -132,8 +129,6 @@ Viewer::Viewer() : vbo_pos_(nullptr), vbo_norm_(nullptr), vbo_color_(nullptr), - shader_flat_(nullptr), - shader_phong_(nullptr), phong_rendering_(true), flat_rendering_(false) {} @@ -168,22 +163,16 @@ void Viewer::draw() if (flat_rendering_) { - shader_flat_->bind(); - shader_flat_->set_matrices(proj,view); - shader_flat_->bind_vao(0); + param_flat_->bind(proj,view); glDrawArrays(GL_TRIANGLES,0,vbo_pos_->size()); - shader_flat_->release_vao(0); - shader_flat_->release(); + param_flat_->release(); } if (phong_rendering_) { - shader_phong_->bind(); - shader_phong_->set_matrices(proj,view); - shader_phong_->bind_vao(0); + param_phong_->bind(proj,view); glDrawArrays(GL_TRIANGLES,0,vbo_pos_->size()); - shader_phong_->release_vao(0); - shader_phong_->release(); + param_phong_->release(); } } @@ -192,9 +181,9 @@ void Viewer::init() glClearColor(0.1f,0.1f,0.3f,0.0f); - vbo_pos_ = new cgogn::rendering::VBO(3); - vbo_norm_ = new cgogn::rendering::VBO(3); - vbo_color_ = new cgogn::rendering::VBO(3); + vbo_pos_ = cgogn::make_unique(3); + vbo_norm_ = cgogn::make_unique(3); + vbo_color_ = cgogn::make_unique(3); // indices of vertices emb (f1_v1,f1_v2,f1_v3, f2_v1,f2_v2,f2_v3, f3_v1...) std::vector ind_v; @@ -205,44 +194,33 @@ void Viewer::init() cgogn::rendering::create_indices_vertices_faces(map_,vertex_position_,ind_v,ind_f); // generate VBO: positions - cgogn::rendering::generate_vbo(vertex_position_, ind_v, *vbo_pos_, [] (const Vec3& v) -> std::array + cgogn::rendering::generate_vbo(vertex_position_, ind_v, vbo_pos_.get(), [] (const Vec3& v) -> std::array { return {float32(v[0]), float32(v[1]), float32(v[2])}; }); // generate VBO: normals - cgogn::rendering::generate_vbo(face_normal_, ind_f, *vbo_norm_, [] (const Vec3& n) -> std::array + cgogn::rendering::generate_vbo(face_normal_, ind_f, vbo_norm_.get(), [] (const Vec3& n) -> std::array { return {float32(n[0]), float32(n[1]), float32(n[2])}; }); // generate VBO: colors (here abs of normals) - cgogn::rendering::generate_vbo(face_normal_, ind_f, *vbo_color_, [] (const Vec3& n) -> std::array + cgogn::rendering::generate_vbo(face_normal_, ind_f, vbo_color_.get(), [] (const Vec3& n) -> std::array { return {float32(std::abs(n[0])), float32(std::abs(n[1])), float32(std::abs(n[2]))}; }); + param_phong_ = cgogn::rendering::ShaderPhongColor::generate_param(); + param_phong_->set_all_vbos(vbo_pos_.get(), vbo_norm_.get(), vbo_color_.get()); + param_phong_->ambiant_color_ = QColor(5, 5, 5); + param_phong_->double_side_ = true; + param_phong_->specular_color_ = QColor(255, 255, 255); + param_phong_->specular_coef_ = 100.0; - shader_phong_ = new cgogn::rendering::ShaderPhong(true); - shader_phong_->add_vao(); - shader_phong_->set_vao(0, vbo_pos_, vbo_norm_, vbo_color_); - shader_phong_->bind(); - shader_phong_->set_ambiant_color(QColor(5,5,5)); - shader_phong_->set_double_side(true); - shader_phong_->set_specular_color(QColor(255,255,255)); - shader_phong_->set_specular_coef(100.0); - shader_phong_->release(); - - - shader_flat_ = new cgogn::rendering::ShaderFlat(true); - shader_flat_->add_vao(); - shader_flat_->set_vao(0, vbo_pos_, vbo_color_); - shader_flat_->bind(); - shader_flat_->set_ambiant_color(QColor(5,5,5)); - shader_flat_->release(); - - - + param_flat_ = cgogn::rendering::ShaderFlatColor::generate_param(); + param_flat_->set_all_vbos(vbo_pos_.get(), vbo_color_.get()); + param_flat_->ambiant_color_ = QColor(5, 5, 5); } int main(int argc, char** argv) diff --git a/cgogn/rendering/examples/viewer_topo.cpp b/cgogn/rendering/examples/viewer_topo.cpp index 0c7224f8..bfa729fe 100644 --- a/cgogn/rendering/examples/viewer_topo.cpp +++ b/cgogn/rendering/examples/viewer_topo.cpp @@ -27,21 +27,22 @@ #include #include -#include +#include -#include -#include +#include -#include -#include -#include -#include +#include -#include +#include +#include +#include +#include +#include +#include -#include - -#include +#include +#include +#include #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) @@ -50,39 +51,44 @@ using Vec3 = Eigen::Vector3d; //using Vec3 = cgogn::geometry::Vec_T>; template -using VertexAttributeHandler = Map2::VertexAttributeHandler; +using VertexAttribute = Map2::VertexAttribute; class Viewer : public QOGLViewer { public: + using MapRender = cgogn::rendering::MapRender; + using TopoDrawer = cgogn::rendering::TopoDrawer; + Viewer(); - Viewer(const Viewer&) = delete; - Viewer& operator=(const Viewer&) = delete; + CGOGN_NOT_COPYABLE_NOR_MOVABLE(Viewer); virtual void draw(); virtual void init(); virtual void keyPressEvent(QKeyEvent *); - void import(const std::string& surfaceMesh); + void import(const std::string& surface_mesh); virtual ~Viewer(); virtual void closeEvent(QCloseEvent *e); private: + Map2 map_; - VertexAttributeHandler vertex_position_; + VertexAttribute vertex_position_; - cgogn::geometry::BoundingBox bb_; + cgogn::geometry::AABB bb_; - cgogn::rendering::MapRender* render_; - cgogn::rendering::VBO* vbo_pos_; - cgogn::rendering::ShaderFlat* shader_flat_; + std::unique_ptr render_; - cgogn::rendering::TopoRender* topo_render; + std::unique_ptr vbo_pos_; - bool flat_rendering_; - bool topo_rendering_; + std::unique_ptr param_flat_; + std::unique_ptr topo_drawer_; + std::unique_ptr topo_drawer_rend_; + + bool flat_rendering_; + bool topo_drawering_; }; @@ -91,19 +97,18 @@ class Viewer : public QOGLViewer // -void Viewer::import(const std::string& surfaceMesh) +void Viewer::import(const std::string& surface_mesh) { - cgogn::io::import_surface(map_, surfaceMesh); + cgogn::io::import_surface(map_, surface_mesh); vertex_position_ = map_.get_attribute("position"); - if (!vertex_position_.is_valid()) { cgogn_log_error("Viewer::import") << "Missing attribute position. Aborting."; std::exit(EXIT_FAILURE); } - cgogn::geometry::compute_bounding_box(vertex_position_, bb_); + cgogn::geometry::compute_AABB(vertex_position_, bb_); setSceneRadius(bb_.diag_size()/2.0); Vec3 center = bb_.center(); setSceneCenter(qoglviewer::Vec(center[0], center[1], center[2])); @@ -115,10 +120,10 @@ Viewer::~Viewer() void Viewer::closeEvent(QCloseEvent*) { - delete render_; - delete vbo_pos_; - delete shader_flat_; - delete topo_render; + render_.reset(); + vbo_pos_.reset(); + topo_drawer_.reset(); + topo_drawer_rend_.reset(); } Viewer::Viewer() : @@ -127,10 +132,10 @@ Viewer::Viewer() : bb_(), render_(nullptr), vbo_pos_(nullptr), - shader_flat_(nullptr), - topo_render(nullptr), + topo_drawer_(nullptr), + topo_drawer_rend_(nullptr), flat_rendering_(true), - topo_rendering_(true) + topo_drawering_(true) {} void Viewer::keyPressEvent(QKeyEvent *ev) @@ -140,14 +145,26 @@ void Viewer::keyPressEvent(QKeyEvent *ev) flat_rendering_ = !flat_rendering_; break; case Qt::Key_T: - topo_rendering_ = !topo_rendering_; + topo_drawering_ = !topo_drawering_; break; - case Qt::Key_C: - cgogn::modeling::catmull_clark(map_,vertex_position_); - cgogn::rendering::update_vbo(vertex_position_, *vbo_pos_); - render_->init_primitives(map_, cgogn::rendering::TRIANGLES, vertex_position_); - topo_render->update_map2(map_,vertex_position_); + cgogn::modeling::catmull_clark(map_, vertex_position_); + cgogn::rendering::update_vbo(vertex_position_, vbo_pos_.get()); + render_->init_primitives(map_, cgogn::rendering::TRIANGLES, &vertex_position_); + topo_drawer_->update(map_, vertex_position_); + break; + case Qt::Key_L: + cgogn::modeling::loop(map_, vertex_position_); + cgogn::rendering::update_vbo(vertex_position_, vbo_pos_.get()); + render_->init_primitives(map_, cgogn::rendering::TRIANGLES, &vertex_position_); + topo_drawer_->update(map_, vertex_position_); + break; + case Qt::Key_R: + cgogn::modeling::pliant_remeshing(map_,vertex_position_); + cgogn::rendering::update_vbo(vertex_position_, vbo_pos_.get()); + render_->init_primitives(map_, cgogn::rendering::TRIANGLES, &vertex_position_); + topo_drawer_->update(map_,vertex_position_); + break; default: break; } @@ -168,58 +185,50 @@ void Viewer::draw() { glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1.0f, 1.0f); - shader_flat_->bind(); - shader_flat_->set_matrices(proj,view); - shader_flat_->bind_vao(0); + param_flat_->bind(proj,view); render_->draw(cgogn::rendering::TRIANGLES); - shader_flat_->release_vao(0); - shader_flat_->release(); + param_flat_->release(); glDisable(GL_POLYGON_OFFSET_FILL); } - if (topo_rendering_) + if (topo_drawering_) { - topo_render->draw(proj,view); + topo_drawer_rend_->draw(proj,view,this); } - } void Viewer::init() { - glClearColor(0.1f,0.1f,0.3f,0.0f); - - vbo_pos_ = new cgogn::rendering::VBO(3); - cgogn::rendering::update_vbo(vertex_position_, *vbo_pos_); - + glClearColor(0.1f, 0.1f, 0.3f, 0.0f); + vbo_pos_ = cgogn::make_unique(3); + cgogn::rendering::update_vbo(vertex_position_, vbo_pos_.get()); - render_ = new cgogn::rendering::MapRender(); - render_->init_primitives(map_, cgogn::rendering::TRIANGLES, vertex_position_); + render_ = cgogn::make_unique(); + render_->init_primitives(map_, cgogn::rendering::TRIANGLES); - shader_flat_ = new cgogn::rendering::ShaderFlat; - shader_flat_->add_vao(); - shader_flat_->set_vao(0, vbo_pos_); - shader_flat_->bind(); - shader_flat_->set_front_color(QColor(0,150,0)); - shader_flat_->set_back_color(QColor(0,0,150)); - shader_flat_->set_ambiant_color(QColor(5,5,5)); - shader_flat_->release(); + param_flat_ = cgogn::rendering::ShaderFlat::generate_param(); + param_flat_->set_position_vbo(vbo_pos_.get()); + param_flat_->front_color_ = QColor(0,150,0); + param_flat_->back_color_ = QColor(0,0,150); + param_flat_->ambiant_color_ = QColor(5,5,5); - topo_render = new cgogn::rendering::TopoRender(this); - topo_render->update_map2(map_,vertex_position_); + topo_drawer_ = cgogn::make_unique(); + topo_drawer_rend_ = topo_drawer_->generate_renderer(); + topo_drawer_->update(map_,vertex_position_); } int main(int argc, char** argv) { - std::string surfaceMesh; + std::string surface_mesh; if (argc < 2) { cgogn_log_info("viewer_topo")<< "USAGE: " << argv[0] << " [filename]"; - surfaceMesh = std::string(DEFAULT_MESH_PATH) + std::string("off/aneurysm_3D.off"); - cgogn_log_info("viewer_topo") << "Using default mesh \"" << surfaceMesh << "\"."; + surface_mesh = std::string(DEFAULT_MESH_PATH) + std::string("off/aneurysm_3D.off"); + cgogn_log_info("viewer_topo") << "Using default mesh \"" << surface_mesh << "\"."; } else - surfaceMesh = std::string(argv[1]); + surface_mesh = std::string(argv[1]); QApplication application(argc, argv); qoglviewer::init_ogl_context(); @@ -227,7 +236,7 @@ int main(int argc, char** argv) // Instantiate the viewer. Viewer viewer; viewer.setWindowTitle("simpleViewer"); - viewer.import(surfaceMesh); + viewer.import(surface_mesh); viewer.show(); // Run main loop. diff --git a/cgogn/rendering/examples/viewer_topo3.cpp b/cgogn/rendering/examples/viewer_topo3.cpp index 2d8505a8..d5428c6b 100644 --- a/cgogn/rendering/examples/viewer_topo3.cpp +++ b/cgogn/rendering/examples/viewer_topo3.cpp @@ -27,16 +27,16 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include @@ -48,15 +48,18 @@ using Vec3 = Eigen::Vector3d; //using Vec3 = cgogn::geometry::Vec_T>; template -using VertexAttributeHandler = Map3::VertexAttributeHandler; +using VertexAttribute = Map3::VertexAttribute; class Viewer : public QOGLViewer { public: + using TopoDrawer = cgogn::rendering::TopoDrawer; + using VolumeDrawer = cgogn::rendering::VolumeDrawer; + using DisplayListDrawer = cgogn::rendering::DisplayListDrawer; + Viewer(); - Viewer(const Viewer&) = delete; - Viewer& operator=(const Viewer&) = delete; + CGOGN_NOT_COPYABLE_NOR_MOVABLE(Viewer); virtual void draw(); virtual void init(); @@ -71,20 +74,24 @@ class Viewer : public QOGLViewer void rayClick(QMouseEvent* event, qoglviewer::Vec& P, qoglviewer::Vec& Q); Map3 map_; - VertexAttributeHandler vertex_position_; + VertexAttribute vertex_position_; + + cgogn::geometry::AABB bb_; - cgogn::geometry::BoundingBox bb_; + std::unique_ptr vbo_pos_; - cgogn::rendering::VBO* vbo_pos_; + std::unique_ptr topo_drawer_; + std::unique_ptr topo_drawer_rend_; - cgogn::rendering::TopoRender* topo_render_; - cgogn::rendering::VolumeRender* volume_render_; + std::unique_ptr volume_drawer_; + std::unique_ptr volume_drawer_rend_; - cgogn::rendering::Drawer* drawer_; + std::unique_ptr drawer_; + std::unique_ptr drawer_rend_; bool vol_rendering_; bool edge_rendering_; - bool topo_rendering_; + bool topo_drawering_; float32 expl_; @@ -112,7 +119,7 @@ void Viewer::import(const std::string& volumeMesh) std::exit(EXIT_FAILURE); } - cgogn::geometry::compute_bounding_box(vertex_position_, bb_); + cgogn::geometry::compute_AABB(vertex_position_, bb_); setSceneRadius(bb_.diag_size()/2.0); Vec3 center = bb_.center(); @@ -127,10 +134,13 @@ Viewer::~Viewer() void Viewer::closeEvent(QCloseEvent*) { - delete vbo_pos_; - delete topo_render_; - delete volume_render_; - delete drawer_; + vbo_pos_.reset(); + topo_drawer_.reset(); + topo_drawer_rend_.reset(); + volume_drawer_.reset(); + volume_drawer_rend_.reset(); + drawer_.reset(); + drawer_rend_.reset(); } Viewer::Viewer() : @@ -138,12 +148,15 @@ Viewer::Viewer() : vertex_position_(), bb_(), vbo_pos_(nullptr), - topo_render_(nullptr), - volume_render_(nullptr), + topo_drawer_(nullptr), + topo_drawer_rend_(nullptr), + volume_drawer_(nullptr), + volume_drawer_rend_(nullptr), drawer_(nullptr), + drawer_rend_(nullptr), vol_rendering_(true), edge_rendering_(true), - topo_rendering_(true), + topo_drawering_(true), expl_(0.8f) {} @@ -158,19 +171,19 @@ void Viewer::keyPressEvent(QKeyEvent *ev) break; case Qt::Key_T: - topo_rendering_ = !topo_rendering_; + topo_drawering_ = !topo_drawering_; break; case Qt::Key_Plus: expl_ += 0.05f; - volume_render_->set_explode_volume(expl_); - topo_render_->set_explode_volume(expl_); - topo_render_->update_map3(map_,vertex_position_); + volume_drawer_rend_->set_explode_volume(expl_); + topo_drawer_->set_explode_volume(expl_); + topo_drawer_->update(map_,vertex_position_); break; case Qt::Key_Minus: expl_ -= 0.05f; - volume_render_->set_explode_volume(expl_); - topo_render_->set_explode_volume(expl_); - topo_render_->update_map3(map_,vertex_position_); + volume_drawer_rend_->set_explode_volume(expl_); + topo_drawer_->set_explode_volume(expl_); + topo_drawer_->update(map_,vertex_position_); break; default: break; @@ -203,11 +216,11 @@ void Viewer::mousePressEvent(QMouseEvent* event) drawer_->begin(GL_LINES); // closest vol in red drawer_->color3f(1.0, 0.0, 0.0); - cgogn::rendering::add_volume_to_drawer(map_, selected[0], vertex_position_, drawer_); + cgogn::rendering::add_volume_to_drawer(map_, selected[0], vertex_position_, drawer_.get()); // others in yellow drawer_->color3f(1.0, 1.0, 0.0); for (uint32 i = 1u; i(map_, selected[i], vertex_position_, drawer_); + cgogn::rendering::add_volume_to_drawer(map_, selected[i], vertex_position_, drawer_.get()); drawer_->end(); } drawer_->line_width(4.0); @@ -220,7 +233,6 @@ void Viewer::mousePressEvent(QMouseEvent* event) drawer_->end_list(); } - QOGLViewer::mousePressEvent(event); } @@ -237,19 +249,19 @@ void Viewer::draw() glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1.0f, 1.0f); - volume_render_->draw_faces(proj,view); + volume_drawer_rend_->draw_faces(proj,view,this); glDisable(GL_POLYGON_OFFSET_FILL); } if (edge_rendering_) - volume_render_->draw_edges(proj,view); + volume_drawer_rend_->draw_edges(proj,view,this); - if (topo_rendering_) - topo_render_->draw(proj,view); + if (topo_drawering_) + topo_drawer_rend_->draw(proj,view,this); - drawer_->call_list(proj, view); + drawer_rend_->draw(proj, view, this); } @@ -257,19 +269,24 @@ void Viewer::init() { glClearColor(0.1f,0.1f,0.3f,0.0f); - vbo_pos_ = new cgogn::rendering::VBO(3); - cgogn::rendering::update_vbo(vertex_position_, *vbo_pos_); + vbo_pos_ = cgogn::make_unique(3); + cgogn::rendering::update_vbo(vertex_position_, vbo_pos_.get()); + + topo_drawer_ = cgogn::make_unique(); + topo_drawer_rend_ = topo_drawer_->generate_renderer(); + topo_drawer_->set_explode_volume(expl_); + topo_drawer_->update(map_,vertex_position_); + + volume_drawer_ = cgogn::make_unique(); + volume_drawer_->update_face(map_,vertex_position_); + volume_drawer_->update_edge(map_,vertex_position_); - topo_render_ = new cgogn::rendering::TopoRender(this); - topo_render_->set_explode_volume(expl_); - topo_render_->update_map3(map_,vertex_position_); + volume_drawer_rend_ = volume_drawer_->generate_renderer(); + volume_drawer_rend_->set_explode_volume(expl_); - volume_render_ = new cgogn::rendering::VolumeRender(this); - volume_render_->set_explode_volume(expl_); - volume_render_->update_face(map_,vertex_position_); - volume_render_->update_edge(map_,vertex_position_); - drawer_ = new cgogn::rendering::Drawer(this); + drawer_ = cgogn::make_unique(); + drawer_rend_ = drawer_->generate_renderer(); } int main(int argc, char** argv) diff --git a/cgogn/rendering/map_render.cpp b/cgogn/rendering/map_render.cpp index 371d0784..98fbd4bf 100644 --- a/cgogn/rendering/map_render.cpp +++ b/cgogn/rendering/map_render.cpp @@ -23,7 +23,7 @@ #define CGOGN_RENDERING_DLL_EXPORT -#include +#include namespace cgogn { @@ -35,20 +35,17 @@ MapRender::MapRender() { for (uint32 i = 0u; i < SIZE_BUFFER; ++i) { - indices_buffers_[i] = new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer); + indices_buffers_[i] = make_unique(QOpenGLBuffer::IndexBuffer); indices_buffers_[i]->setUsagePattern(QOpenGLBuffer::StaticDraw); } } MapRender::~MapRender() -{ - for (uint32 i = 0u; i < SIZE_BUFFER; ++i) - delete indices_buffers_[i]; -} +{} void MapRender::draw(DrawingType prim) { - QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); indices_buffers_[prim]->bind(); switch (prim) @@ -69,6 +66,6 @@ void MapRender::draw(DrawingType prim) indices_buffers_[prim]->release(); } - } // namespace rendering + } // namespace io diff --git a/cgogn/rendering/map_render.h b/cgogn/rendering/map_render.h index 2022b91b..4875db31 100644 --- a/cgogn/rendering/map_render.h +++ b/cgogn/rendering/map_render.h @@ -22,17 +22,20 @@ * * *******************************************************************************/ -#ifndef RENDERING_MAP_RENDER_H_ -#define RENDERING_MAP_RENDER_H_ +#ifndef CGOGN_RENDERING_MAP_RENDER_H_ +#define CGOGN_RENDERING_MAP_RENDER_H_ -#include -#include +#include + +#include // impossible to include directly attribute.h ! + +#include -#include // impossible to include directly attribute_handler.h ! -#include -#include +#include +#include -#include +#include +#include namespace cgogn { @@ -52,23 +55,26 @@ class CGOGN_RENDERING_API MapRender { protected: - QOpenGLBuffer* indices_buffers_[SIZE_BUFFER]; - bool indices_buffers_uptodate_[SIZE_BUFFER]; - uint32 nb_indices_[SIZE_BUFFER]; + std::array, SIZE_BUFFER> indices_buffers_; + std::array indices_buffers_uptodate_; + std::array nb_indices_; public: + using Self = MapRender; MapRender(); CGOGN_NOT_COPYABLE_NOR_MOVABLE(MapRender); ~MapRender(); - inline bool is_primitive_uptodate(DrawingType prim) { return indices_buffers_uptodate_[prim]; } + inline bool is_primitive_uptodate(DrawingType prim) { return indices_buffers_uptodate_[prim]; } + + inline void set_primitive_dirty(DrawingType prim) { indices_buffers_uptodate_[prim] = false; } template - inline void init_points(MAP& m, std::vector& table_indices) + inline void init_points(const MAP& m, std::vector& table_indices) { - // table_indices.reserve(m.get_nb_darts()/6); +// table_indices.reserve(m.get_nb_darts() / 6); m.foreach_cell([&] (typename MAP::Vertex v) { table_indices.push_back(m.get_embedding(v)); @@ -76,11 +82,11 @@ class CGOGN_RENDERING_API MapRender } template - inline void init_lines(MAP& m, std::vector& table_indices) + inline void init_lines(const MAP& m, std::vector& table_indices) { using Vertex = typename MAP::Vertex; using Edge = typename MAP::Edge; - // table_indices.reserve(m.get_nb_darts()/2); +// table_indices.reserve(m.get_nb_darts() / 2); m.foreach_cell([&] (Edge e) { table_indices.push_back(m.get_embedding(Vertex(e.dart))); @@ -89,12 +95,35 @@ class CGOGN_RENDERING_API MapRender } template - inline void init_triangles(MAP& m, std::vector& table_indices, const typename MAP::template VertexAttributeHandler& position) + inline void init_triangles(const MAP& m, std::vector& table_indices) { using Vertex = typename MAP::Vertex; using Face = typename MAP::Face; // reserve more ? - // table_indices.reserve(m.get_nb_darts()/3); +// table_indices.reserve(m.get_nb_darts() / 3); + m.foreach_cell([&] (Face f) + { + Dart d0 = f.dart; + Dart d1 = m.phi1(d0); + Dart d2 = m.phi1(d1); + do + { + table_indices.push_back(m.get_embedding(Vertex(d0))); + table_indices.push_back(m.get_embedding(Vertex(d1))); + table_indices.push_back(m.get_embedding(Vertex(d2))); + d1 = d2; + d2 = m.phi1(d1); + } while(d2 != d0); + }); + } + + template + inline void init_triangles_ear(const MAP& m, std::vector& table_indices, const typename MAP::template VertexAttribute* position) + { + using Vertex = typename MAP::Vertex; + using Face = typename MAP::Face; + // reserve more ? +// table_indices.reserve(m.get_nb_darts() / 3); m.foreach_cell([&] (Face f) { if (m.has_codegree(f, 3)) @@ -104,14 +133,12 @@ class CGOGN_RENDERING_API MapRender table_indices.push_back(m.get_embedding(Vertex(m.phi1(m.phi1(f.dart))))); } else - { - cgogn::geometry::compute_ear_triangulation(m, f, position, table_indices); - } + cgogn::geometry::compute_ear_triangulation(m, f, *position, table_indices); }); } template - inline void init_primitives(MAP& m, DrawingType prim, const typename MAP::template VertexAttributeHandler& position) + inline void init_primitives(const MAP& m, DrawingType prim, const typename MAP::template VertexAttribute* position = nullptr) { std::vector table_indices; @@ -124,7 +151,10 @@ class CGOGN_RENDERING_API MapRender init_lines(m, table_indices); break; case TRIANGLES: - init_triangles(m, table_indices, position); + if (position) + init_triangles_ear(m, table_indices, position); + else + init_triangles(m, table_indices); break; default: break; @@ -143,8 +173,6 @@ class CGOGN_RENDERING_API MapRender void draw(DrawingType prim); }; - - /** * @brief create embedding indices of vertices and faces for arch vertx of each face * @param m @@ -153,7 +181,7 @@ class CGOGN_RENDERING_API MapRender * @param indices2 embedding indices of faces */ template -void create_indices_vertices_faces(MAP& m, const typename MAP::template VertexAttributeHandler& position, std::vector& indices1, std::vector& indices2) +void create_indices_vertices_faces(const MAP& m, const typename MAP::template VertexAttribute& position, std::vector& indices1, std::vector& indices2) { using Vertex = typename MAP::Vertex; using Face = typename MAP::Face; @@ -169,7 +197,6 @@ void create_indices_vertices_faces(MAP& m, const typename MAP::template VertexAt m.foreach_cell([&] (Face f) { - uint32 ef = m.get_embedding(Face(f.dart)); if (m.has_codegree(f, 3)) { @@ -179,11 +206,10 @@ void create_indices_vertices_faces(MAP& m, const typename MAP::template VertexAt indices2.push_back(ef); indices2.push_back(ef); indices2.push_back(ef); - } else { - cgogn::geometry::compute_ear_triangulation(m,f,position,local_vert_indices); + cgogn::geometry::compute_ear_triangulation(m, f, position, local_vert_indices); for (uint32 i : local_vert_indices) { indices1.push_back(i); @@ -193,18 +219,16 @@ void create_indices_vertices_faces(MAP& m, const typename MAP::template VertexAt }); } - template -void add_edge_to_drawer(MAP& m, typename MAP::Edge e, const typename MAP::template VertexAttributeHandler& position, Drawer* dr) +void add_edge_to_drawer(const MAP& m, typename MAP::Edge e, const typename MAP::template VertexAttribute& position, DisplayListDrawer* dr) { using Vertex = typename MAP::Vertex; dr->vertex3fv(position[Vertex(e.dart)]); dr->vertex3fv(position[Vertex(m.phi1(e.dart))]); } - template -void add_face_to_drawer(MAP& m, typename MAP::Face f, const typename MAP::template VertexAttributeHandler& position, Drawer* dr) +void add_face_to_drawer(const MAP& m, typename MAP::Face f, const typename MAP::template VertexAttribute& position, DisplayListDrawer* dr) { using Vertex = typename MAP::Vertex; using Edge = typename MAP::Edge; @@ -216,7 +240,7 @@ void add_face_to_drawer(MAP& m, typename MAP::Face f, const typename MAP::templa } template -void add_volume_to_drawer(MAP& m, typename MAP::Volume vo, const typename MAP::template VertexAttributeHandler& position, Drawer* dr) +void add_volume_to_drawer(const MAP& m, typename MAP::Volume vo, const typename MAP::template VertexAttribute& position, DisplayListDrawer* dr) { using Vertex = typename MAP::Vertex; using Edge = typename MAP::Edge; @@ -225,12 +249,10 @@ void add_volume_to_drawer(MAP& m, typename MAP::Volume vo, const typename MAP::t dr->vertex3fv(position[Vertex(e.dart)]); dr->vertex3fv(position[Vertex(m.phi1(e.dart))]); }); - } - } // namespace rendering } // namespace cgogn -#endif // RENDERING_MAP_RENDER_H_ +#endif // CGOGN_RENDERING_MAP_RENDER_H_ diff --git a/cgogn/rendering/shaders/shader_bold_line.cpp b/cgogn/rendering/shaders/shader_bold_line.cpp index becb8ed2..360f06af 100644 --- a/cgogn/rendering/shaders/shader_bold_line.cpp +++ b/cgogn/rendering/shaders/shader_bold_line.cpp @@ -22,13 +22,12 @@ *******************************************************************************/ #define CGOGN_RENDERING_DLL_EXPORT +#define CGOGN_RENDER_SHADERS_BOLD_LINE_CPP_ #include -#include -#include - -#include +#include +#include namespace cgogn { @@ -36,15 +35,14 @@ namespace cgogn namespace rendering { -const char* ShaderBoldLine::vertex_shader_source_ = +const char* ShaderBoldLineGen::vertex_shader_source_ = "#version 150\n" "in vec3 vertex_pos;\n" "void main() {\n" " gl_Position = vec4(vertex_pos,1.0);\n" "}\n"; - -const char* ShaderBoldLine::geometry_shader_source_ = +const char* ShaderBoldLineGen::geometry_shader_source_ = "#version 150\n" "layout (lines) in;\n" "layout (triangle_strip, max_vertices=6) out;\n" @@ -97,8 +95,7 @@ const char* ShaderBoldLine::geometry_shader_source_ = " }\n" "}\n"; - -const char* ShaderBoldLine::fragment_shader_source_ = +const char* ShaderBoldLineGen::fragment_shader_source_ = "#version 150\n" "in vec4 color_f;\n" "out vec4 fragColor;\n" @@ -106,10 +103,7 @@ const char* ShaderBoldLine::fragment_shader_source_ = " fragColor = color_f;\n" "}\n"; - - - -const char* ShaderBoldLine::vertex_shader_source2_ = +const char* ShaderBoldLineGen::vertex_shader_source2_ = "#version 150\n" "in vec3 vertex_pos;\n" "in vec3 vertex_color;\n" @@ -119,8 +113,7 @@ const char* ShaderBoldLine::vertex_shader_source2_ = " gl_Position = vec4(vertex_pos,1.0);\n" "}\n"; - -const char* ShaderBoldLine::geometry_shader_source2_ = +const char* ShaderBoldLineGen::geometry_shader_source2_ = "#version 150\n" "layout (lines) in;\n" "layout (triangle_strip, max_vertices=6) out;\n" @@ -172,8 +165,7 @@ const char* ShaderBoldLine::geometry_shader_source2_ = " }\n" "}\n"; - -const char* ShaderBoldLine::fragment_shader_source2_ = +const char* ShaderBoldLineGen::fragment_shader_source2_ = "#version 150\n" "in vec4 color_f;\n" "out vec4 fragColor;\n" @@ -182,8 +174,7 @@ const char* ShaderBoldLine::fragment_shader_source2_ = "}\n"; - -ShaderBoldLine::ShaderBoldLine(bool color_per_vertex) +ShaderBoldLineGen::ShaderBoldLineGen(bool color_per_vertex) { if (color_per_vertex) { @@ -192,8 +183,6 @@ ShaderBoldLine::ShaderBoldLine(bool color_per_vertex) prg_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader_source2_); prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); prg_.bindAttributeLocation("vertex_color", ATTRIB_COLOR); - prg_.link(); - get_matrices_uniforms(); } else { @@ -201,64 +190,32 @@ ShaderBoldLine::ShaderBoldLine(bool color_per_vertex) prg_.addShaderFromSourceCode(QOpenGLShader::Geometry, geometry_shader_source_); prg_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader_source_); prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); - prg_.link(); - get_matrices_uniforms(); } + prg_.link(); + get_matrices_uniforms(); unif_color_ = prg_.uniformLocation("lineColor"); unif_width_ = prg_.uniformLocation("lineWidths"); - } - - -void ShaderBoldLine::set_color(const QColor& rgb) +void ShaderBoldLineGen::set_color(const QColor& rgb) { if (unif_color_ >= 0) prg_.setUniformValue(unif_color_, rgb); } -void ShaderBoldLine::set_width(float32 wpix) +void ShaderBoldLineGen::set_width(float32 w) { - QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); GLint viewport[4]; ogl->glGetIntegerv(GL_VIEWPORT, viewport); - QSizeF wd(wpix / float32(viewport[2]), wpix / float32(viewport[3])); + QSizeF wd(w / float32(viewport[2]), w / float32(viewport[3])); prg_.setUniformValue(unif_width_, wd); } -bool ShaderBoldLine::set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_color) -{ - if (i >= vaos_.size()) - { - cgogn_log_warning("set_vao") << "VAO number " << i << " does not exist."; - return false; - } - - QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); - - prg_.bind(); - vaos_[i]->bind(); - - // position vbo - vbo_pos->bind(); - ogl->glEnableVertexAttribArray(ATTRIB_POS); - ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); - vbo_pos->release(); - - if (vbo_color) - { - // color vbo - vbo_color->bind(); - ogl->glEnableVertexAttribArray(ATTRIB_COLOR); - ogl->glVertexAttribPointer(ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); - vbo_color->release(); - } - - vaos_[i]->release(); - prg_.release(); - - return true; -} +template class CGOGN_RENDERING_API ShaderBoldLineTpl; +template class CGOGN_RENDERING_API ShaderBoldLineTpl; +template class CGOGN_RENDERING_API ShaderParamBoldLine; +template class CGOGN_RENDERING_API ShaderParamBoldLine; } // namespace rendering diff --git a/cgogn/rendering/shaders/shader_bold_line.h b/cgogn/rendering/shaders/shader_bold_line.h index 6fc369b8..94bd28fa 100644 --- a/cgogn/rendering/shaders/shader_bold_line.h +++ b/cgogn/rendering/shaders/shader_bold_line.h @@ -21,12 +21,15 @@ * * *******************************************************************************/ -#ifndef RENDERING_SHADERS_BOLDLINE_H_ -#define RENDERING_SHADERS_BOLDLINE_H_ +#ifndef CGOGN_RENDERING_SHADERS_BOLDLINE_H_ +#define CGOGN_RENDERING_SHADERS_BOLDLINE_H_ -#include -#include -#include +#include +#include +#include + +#include +#include namespace cgogn { @@ -34,8 +37,17 @@ namespace cgogn namespace rendering { -class CGOGN_RENDERING_API ShaderBoldLine : public ShaderProgram +// forward +template +class ShaderParamBoldLine : public ShaderParam +{}; + +class CGOGN_RENDERING_API ShaderBoldLineGen : public ShaderProgram { + template friend class ShaderParamBoldLine; + +protected: + static const char* vertex_shader_source_; static const char* geometry_shader_source_; static const char* fragment_shader_source_; @@ -44,19 +56,20 @@ class CGOGN_RENDERING_API ShaderBoldLine : public ShaderProgram static const char* geometry_shader_source2_; static const char* fragment_shader_source2_; - enum - { - ATTRIB_POS = 0, - ATTRIB_COLOR - }; - // uniform ids GLint unif_color_; GLint unif_width_; public: - ShaderBoldLine(bool color_per_vertex = false); + using Self = ShaderBoldLineGen; + CGOGN_NOT_COPYABLE_NOR_MOVABLE(ShaderBoldLineGen); + + enum + { + ATTRIB_POS = 0, + ATTRIB_COLOR + }; /** * @brief set current color @@ -70,18 +83,161 @@ class CGOGN_RENDERING_API ShaderBoldLine : public ShaderProgram */ void set_width(float32 w); - /** - * @brief set a vao configuration - * @param i vao id (0,1,...) - * @param vbo_pos pointer on position vbo (XYZ) - * @param vbo_color pointer on color vbo - * @return true if ok - */ - bool set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_color=NULL); +protected: + + ShaderBoldLineGen(bool color_per_vertex); +}; + +template +class ShaderBoldLineTpl : public ShaderBoldLineGen +{ +public: + + using Param = ShaderParamBoldLine; + static std::unique_ptr generate_param(); + +private: + + ShaderBoldLineTpl() : ShaderBoldLineGen(CPV) {} + static std::unique_ptr instance_; +}; + +template +std::unique_ptr> ShaderBoldLineTpl::instance_ = nullptr; + + +// COLOR UNIFORM VERSION +template <> +class ShaderParamBoldLine : public ShaderParam +{ +protected: + + void set_uniforms() override + { + ShaderBoldLineGen* sh = static_cast(this->shader_); + sh->set_color(color_); + sh->set_width(width_); + } + +public: + + QColor color_; + float32 width_; + + ShaderParamBoldLine(ShaderBoldLineTpl* sh) : + ShaderParam(sh), + color_(255, 255, 255), + width_(2.0f) + {} + + void set_position_vbo(VBO* vbo_pos) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + // position vbo + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderBoldLineGen::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderBoldLineGen::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + vao_->release(); + shader_->release(); + } +}; + +// COLOR PER VERTEX VERSION +template <> +class ShaderParamBoldLine : public ShaderParam +{ +protected: + + void set_uniforms() override + { + ShaderBoldLineGen* sh = static_cast(this->shader_); + sh->set_width(width_); + } + +public: + + using Self = ShaderParamBoldLine; + CGOGN_NOT_COPYABLE_NOR_MOVABLE(ShaderParamBoldLine); + + float32 width_; + + ShaderParamBoldLine(ShaderBoldLineTpl* sh) : + ShaderParam(sh), + width_(2.0f) + {} + + void set_all_vbos(VBO* vbo_pos, VBO* vbo_color) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + // position vbo + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderBoldLineGen::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderBoldLineGen::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + // color vbo + vbo_color->bind(); + ogl->glEnableVertexAttribArray(ShaderBoldLineGen::ATTRIB_COLOR); + ogl->glVertexAttribPointer(ShaderBoldLineGen::ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_color->release(); + vao_->release(); + shader_->release(); + } + + void set_position_vbo(VBO* vbo_pos) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderBoldLineGen::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderBoldLineGen::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + vao_->release(); + shader_->release(); + } + + void set_color_vbo(VBO* vbo_color) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_color->bind(); + ogl->glEnableVertexAttribArray(ShaderBoldLineGen::ATTRIB_COLOR); + ogl->glVertexAttribPointer(ShaderBoldLineGen::ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_color->release(); + vao_->release(); + shader_->release(); + } }; + +template +std::unique_ptr::Param> ShaderBoldLineTpl::generate_param() +{ + if (!instance_) + instance_ = std::unique_ptr(new ShaderBoldLineTpl); + return cgogn::make_unique(instance_.get()); +} + + +using ShaderBoldLine = ShaderBoldLineTpl; +using ShaderBoldLineColor = ShaderBoldLineTpl; + + +#if !defined(CGOGN_RENDER_SHADERS_BOLD_LINE_CPP_) +extern template class CGOGN_RENDERING_API ShaderBoldLineTpl; +extern template class CGOGN_RENDERING_API ShaderBoldLineTpl; +extern template class CGOGN_RENDERING_API ShaderParamBoldLine; +extern template class CGOGN_RENDERING_API ShaderParamBoldLine; +#endif + } // namespace rendering } // namespace cgogn -#endif // RENDERING_SHADERS_BOLDLINE_H_ +#endif // CGOGN_RENDERING_SHADERS_BOLDLINE_H_ diff --git a/cgogn/rendering/shaders/shader_color_per_vertex.cpp b/cgogn/rendering/shaders/shader_color_per_vertex.cpp index bdfd0c00..23f64b8c 100644 --- a/cgogn/rendering/shaders/shader_color_per_vertex.cpp +++ b/cgogn/rendering/shaders/shader_color_per_vertex.cpp @@ -23,17 +23,18 @@ #define CGOGN_RENDERING_DLL_EXPORT -#include - -#include #include +#include + namespace cgogn { namespace rendering { +std::unique_ptr ShaderColorPerVertex::instance_ = nullptr; + const char* ShaderColorPerVertex::vertex_shader_source_ = "#version 150\n" "in vec3 vertex_pos;\n" @@ -54,47 +55,21 @@ const char* ShaderColorPerVertex::fragment_shader_source_ = " fragColor = color_v;\n" "}\n"; - ShaderColorPerVertex::ShaderColorPerVertex() { prg_.addShaderFromSourceCode(QOpenGLShader::Vertex, vertex_shader_source_); prg_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader_source_); prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); prg_.bindAttributeLocation("vertex_color", ATTRIB_COLOR); - prg_.link(); - + prg_.link(); get_matrices_uniforms(); } -bool ShaderColorPerVertex::set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_color) +std::unique_ptr ShaderColorPerVertex::generate_param() { - if (i >= vaos_.size()) - { - cgogn_log_warning("set_vao") << "VAO number " << i << " does not exist."; - return false; - } - - QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); - - prg_.bind(); - vaos_[i]->bind(); - - // position vbo - vbo_pos->bind(); - ogl->glEnableVertexAttribArray(ATTRIB_POS); - ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); - vbo_pos->release(); - - // color vbo - vbo_color->bind(); - ogl->glEnableVertexAttribArray(ATTRIB_COLOR); - ogl->glVertexAttribPointer(ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); - vbo_color->release(); - - vaos_[i]->release(); - prg_.release(); - - return true; + if (!instance_) + instance_ = std::unique_ptr(new ShaderColorPerVertex); + return cgogn::make_unique(instance_.get()); } } // namespace rendering diff --git a/cgogn/rendering/shaders/shader_color_per_vertex.h b/cgogn/rendering/shaders/shader_color_per_vertex.h index 4edc8b6c..828db02e 100644 --- a/cgogn/rendering/shaders/shader_color_per_vertex.h +++ b/cgogn/rendering/shaders/shader_color_per_vertex.h @@ -21,12 +21,14 @@ * * *******************************************************************************/ -#ifndef RENDERING_SHADERS_COLORPERVERTEX_H_ -#define RENDERING_SHADERS_COLORPERVERTEX_H_ +#ifndef CGOGN_RENDERING_SHADERS_COLORPERVERTEX_H_ +#define CGOGN_RENDERING_SHADERS_COLORPERVERTEX_H_ -#include -#include -#include +#include +#include +#include + +#include namespace cgogn { @@ -34,33 +36,100 @@ namespace cgogn namespace rendering { +// forward +class ShaderParamColorPerVertex; + class CGOGN_RENDERING_API ShaderColorPerVertex : public ShaderProgram { + friend class ShaderParamColorPerVertex; + +protected: + static const char* vertex_shader_source_; static const char* fragment_shader_source_; +public: + enum { ATTRIB_POS = 0, ATTRIB_COLOR }; + using Param = ShaderParamColorPerVertex; + static std::unique_ptr generate_param(); + +protected: + + ShaderColorPerVertex(); + static std::unique_ptr instance_; +}; + +class CGOGN_RENDERING_API ShaderParamColorPerVertex : public ShaderParam +{ +protected: + + inline void set_uniforms() override + {} + public: - ShaderColorPerVertex(); + ShaderParamColorPerVertex(ShaderColorPerVertex* prg) : ShaderParam(prg) + {} /** - * @brief set a vao configuration - * @param i vao id (0,1,...) + * @brief set a vbo configuration * @param vbo_pos pointer on position vbo (XYZ) * @param vbo_col pointer on color vbo (RGB) - * @return true if ok */ - bool set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_col); + void set_all_vbos(VBO* vbo_pos, VBO* vbo_color) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + // position vbo + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderColorPerVertex::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderColorPerVertex::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + // color vbo + vbo_color->bind(); + ogl->glEnableVertexAttribArray(ShaderColorPerVertex::ATTRIB_COLOR); + ogl->glVertexAttribPointer(ShaderColorPerVertex::ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_color->release(); + vao_->release(); + shader_->release(); + } + + void set_position_vbo(VBO* vbo_pos) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderColorPerVertex::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderColorPerVertex::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + vao_->release(); + shader_->release(); + } + + void set_color_vbo(VBO* vbo_color) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_color->bind(); + ogl->glEnableVertexAttribArray(ShaderColorPerVertex::ATTRIB_COLOR); + ogl->glVertexAttribPointer(ShaderColorPerVertex::ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_color->release(); + vao_->release(); + shader_->release(); + } }; } // namespace rendering } // namespace cgogn -#endif // RENDERING_SHADERS_COLORPERVERTEX_H_ +#endif // CGOGN_RENDERING_SHADERS_COLORPERVERTEX_H_ diff --git a/cgogn/rendering/shaders/shader_explode_volumes.cpp b/cgogn/rendering/shaders/shader_explode_volumes.cpp index 33809450..1ffa3f1b 100644 --- a/cgogn/rendering/shaders/shader_explode_volumes.cpp +++ b/cgogn/rendering/shaders/shader_explode_volumes.cpp @@ -22,26 +22,28 @@ *******************************************************************************/ #define CGOGN_RENDERING_DLL_EXPORT +#define CGOGN_RENDER_SHADERS_EXPLODE_VOLUME_CPP_ -#include -#include -#include #include +#include + + + namespace cgogn { namespace rendering { -const char* ShaderExplodeVolumes::vertex_shader_source_ = +const char* ShaderExplodeVolumesGen::vertex_shader_source_ = "#version 150\n" "in vec3 vertex_pos;\n" "void main() {\n" " gl_Position = vec4(vertex_pos,1.0);\n" "}\n"; -const char* ShaderExplodeVolumes::geometry_shader_source_ = +const char* ShaderExplodeVolumesGen::geometry_shader_source_ = "#version 150\n" "layout (lines_adjacency) in;\n" "layout (triangle_strip, max_vertices=3) out;\n" @@ -75,8 +77,7 @@ const char* ShaderExplodeVolumes::geometry_shader_source_ = " }\n" "}\n"; - -const char* ShaderExplodeVolumes::fragment_shader_source_ = +const char* ShaderExplodeVolumesGen::fragment_shader_source_ = "#version 150\n" "in vec3 color_f;\n" "out vec3 fragColor;\n" @@ -84,7 +85,7 @@ const char* ShaderExplodeVolumes::fragment_shader_source_ = " fragColor = color_f;\n" "}\n"; -const char* ShaderExplodeVolumes::vertex_shader_source2_ = +const char* ShaderExplodeVolumesGen::vertex_shader_source2_ = "#version 150\n" "in vec3 vertex_pos;\n" "in vec3 vertex_color;\n" @@ -94,7 +95,7 @@ const char* ShaderExplodeVolumes::vertex_shader_source2_ = " gl_Position = vec4(vertex_pos,1.0);\n" "}\n"; -const char* ShaderExplodeVolumes::geometry_shader_source2_ = +const char* ShaderExplodeVolumesGen::geometry_shader_source2_ = "#version 150\n" "layout (lines_adjacency) in;\n" "layout (triangle_strip, max_vertices=3) out;\n" @@ -128,8 +129,7 @@ const char* ShaderExplodeVolumes::geometry_shader_source2_ = " }\n" "}\n"; - -const char* ShaderExplodeVolumes::fragment_shader_source2_ = +const char* ShaderExplodeVolumesGen::fragment_shader_source2_ = "#version 150\n" "in vec3 color_f;\n" "out vec3 fragColor;\n" @@ -138,7 +138,8 @@ const char* ShaderExplodeVolumes::fragment_shader_source2_ = "}\n"; -ShaderExplodeVolumes::ShaderExplodeVolumes(bool color_per_vertex) + +ShaderExplodeVolumesGen::ShaderExplodeVolumesGen(bool color_per_vertex) { if (color_per_vertex) { @@ -162,7 +163,7 @@ ShaderExplodeVolumes::ShaderExplodeVolumes(bool color_per_vertex) unif_light_position_ = prg_.uniformLocation("light_position"); unif_color_ = prg_.uniformLocation("color"); - //default param + // default param bind(); set_light_position(QVector3D(10.0f,100.0f,1000.0f)); set_explode_volume(0.8f); @@ -171,62 +172,32 @@ ShaderExplodeVolumes::ShaderExplodeVolumes(bool color_per_vertex) release(); } -void ShaderExplodeVolumes::set_color(const QColor& rgb) +void ShaderExplodeVolumesGen::set_color(const QColor& rgb) { - if (unif_color_>=0) - prg_.setUniformValue(unif_color_,rgb); + if (unif_color_ >= 0) + prg_.setUniformValue(unif_color_, rgb); } -void ShaderExplodeVolumes::set_light_position(const QVector3D& l) +void ShaderExplodeVolumesGen::set_light_position(const QVector3D& l) { - prg_.setUniformValue(unif_light_position_,l); + prg_.setUniformValue(unif_light_position_, l); } - -void ShaderExplodeVolumes::set_explode_volume(float32 x) +void ShaderExplodeVolumesGen::set_explode_volume(float32 x) { - prg_.setUniformValue(unif_expl_v_, x); + prg_.setUniformValue(unif_expl_v_, x); } -void ShaderExplodeVolumes::set_plane_clip(const QVector4D& plane) +void ShaderExplodeVolumesGen::set_plane_clip(const QVector4D& plane) { - prg_.setUniformValue(unif_plane_clip_, plane); } -bool ShaderExplodeVolumes::set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_color) -{ - if (i >= vaos_.size()) - { - cgogn_log_warning("set_vao") << "VAO number " << i << " does not exist."; - return false; - } - - QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); - - prg_.bind(); - vaos_[i]->bind(); - // position vbo - vbo_pos->bind(); - ogl->glEnableVertexAttribArray(ATTRIB_POS); - ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); - vbo_pos->release(); - - if (vbo_color) - { - // color vbo - vbo_color->bind(); - ogl->glEnableVertexAttribArray(ATTRIB_COLOR); - ogl->glVertexAttribPointer(ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); - vbo_color->release(); - } - - vaos_[i]->release(); - prg_.release(); - - return true; -} +template class CGOGN_RENDERING_API ShaderExplodeVolumesTpl; +template class CGOGN_RENDERING_API ShaderExplodeVolumesTpl; +template class CGOGN_RENDERING_API ShaderParamExplodeVolumes; +template class CGOGN_RENDERING_API ShaderParamExplodeVolumes; } // namespace rendering diff --git a/cgogn/rendering/shaders/shader_explode_volumes.h b/cgogn/rendering/shaders/shader_explode_volumes.h index cbb096cc..ecc41598 100644 --- a/cgogn/rendering/shaders/shader_explode_volumes.h +++ b/cgogn/rendering/shaders/shader_explode_volumes.h @@ -21,14 +21,17 @@ * * *******************************************************************************/ -#ifndef RENDERING_SHADERS_EXPLODE_VOLUMES_H_ -#define RENDERING_SHADERS_EXPLODE_VOLUMES_H_ +#ifndef CGOGN_RENDERING_SHADERS_EXPLODE_VOLUMES_H_ +#define CGOGN_RENDERING_SHADERS_EXPLODE_VOLUMES_H_ + +#include +#include +#include #include #include -#include -#include -#include +#include +#include namespace cgogn { @@ -36,8 +39,17 @@ namespace cgogn namespace rendering { -class CGOGN_RENDERING_API ShaderExplodeVolumes : public ShaderProgram +// forward +template +class ShaderParamExplodeVolumes +{}; + +class CGOGN_RENDERING_API ShaderExplodeVolumesGen : public ShaderProgram { + template friend class ShaderParamExplodeVolumes; + +protected: + static const char* vertex_shader_source_; static const char* geometry_shader_source_; static const char* fragment_shader_source_; @@ -46,43 +58,191 @@ class CGOGN_RENDERING_API ShaderExplodeVolumes : public ShaderProgram static const char* geometry_shader_source2_; static const char* fragment_shader_source2_; + // uniform ids + GLint unif_expl_v_; + GLint unif_light_position_; + GLint unif_plane_clip_; + GLint unif_color_; + +public: + + using Self = ShaderExplodeVolumesGen; + CGOGN_NOT_COPYABLE_NOR_MOVABLE(ShaderExplodeVolumesGen); + enum { ATTRIB_POS = 0, ATTRIB_COLOR }; - // uniform ids - GLint unif_expl_v_; - GLint unif_light_position_; - GLint unif_plane_clip_; - GLint unif_color_; + void set_explode_volume(float32 x); + void set_light_position(const QVector3D& l); + void set_plane_clip(const QVector4D& plane); + void set_color(const QColor& rgb); +protected: + ShaderExplodeVolumesGen(bool color_per_vertex); +}; + +template +class ShaderExplodeVolumesTpl : public ShaderExplodeVolumesGen +{ public: - ShaderExplodeVolumes(bool color_per_vertex = false); + using Param = ShaderParamExplodeVolumes; + static std::unique_ptr generate_param(); - void set_explode_volume(float32 x); +private: - void set_light_position(const QVector3D& l); + ShaderExplodeVolumesTpl() : ShaderExplodeVolumesGen(CPV) {} + static std::unique_ptr instance_; +}; - void set_plane_clip(const QVector4D& plane); +template +std::unique_ptr> ShaderExplodeVolumesTpl::instance_ = nullptr; - void set_color(const QColor& rgb); - /** - * @brief set a vao configuration - * @param i vao id (0,1,...) - * @param vbo_pos pointer on position vbo (XYZ) - * @param vbo_color pointer on color vbo - * @return true if ok - */ - bool set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_color = nullptr); +// COLOR UNIFORM PARAM +template <> +class ShaderParamExplodeVolumes : public ShaderParam +{ +protected: + + void set_uniforms() override + { + ShaderExplodeVolumesGen* sh = static_cast(this->shader_); + sh->set_color(color_); + sh->set_explode_volume(explode_factor_); + sh->set_light_position(light_position_); + sh->set_plane_clip(plane_clip_); + } + +public: + + QColor color_; + QVector4D plane_clip_; + QVector3D light_position_; + float32 explode_factor_; + + ShaderParamExplodeVolumes(ShaderExplodeVolumesTpl* sh) : + ShaderParam(sh), + color_(255, 0, 0), + plane_clip_(0, 0, 0, 0), + light_position_(10.0f, 100.0f, 1000.0f), + explode_factor_(0.8f) + {} + + void set_position_vbo(VBO* vbo_pos) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderExplodeVolumesGen::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderExplodeVolumesGen::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + vao_->release(); + shader_->release(); + } }; +// COLOR PER VERTEX PARAM +template <> +class ShaderParamExplodeVolumes : public ShaderParam +{ +protected: + + void set_uniforms() override + { + ShaderExplodeVolumesGen* sh = static_cast(this->shader_); + sh->set_explode_volume(explode_factor_); + sh->set_light_position(light_position_); + sh->set_plane_clip(plane_clip_); + } + +public: + + QVector4D plane_clip_; + QVector3D light_position_; + float32 explode_factor_; + + ShaderParamExplodeVolumes(ShaderExplodeVolumesTpl* sh) : + ShaderParam(sh), + plane_clip_(0, 0, 0, 0), + light_position_(10.0f, 100.0f, 1000.0f), + explode_factor_(0.8f) + {} + + void set_all_vbos(VBO* vbo_pos, VBO* vbo_color) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + // position vbo + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderExplodeVolumesGen::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderExplodeVolumesGen::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + // color vbo + vbo_color->bind(); + ogl->glEnableVertexAttribArray(ShaderExplodeVolumesGen::ATTRIB_COLOR); + ogl->glVertexAttribPointer(ShaderExplodeVolumesGen::ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_color->release(); + vao_->release(); + shader_->release(); + } + + void set_position_vbo(VBO* vbo_pos) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderExplodeVolumesGen::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderExplodeVolumesGen::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + vao_->release(); + shader_->release(); + } + + void set_color_vbo(VBO* vbo_color) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_color->bind(); + ogl->glEnableVertexAttribArray(ShaderExplodeVolumesGen::ATTRIB_COLOR); + ogl->glVertexAttribPointer(ShaderExplodeVolumesGen::ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_color->release(); + vao_->release(); + shader_->release(); + } +}; + + +template +std::unique_ptr::Param> ShaderExplodeVolumesTpl::generate_param() +{ + if (!instance_) + instance_ = std::unique_ptr(new ShaderExplodeVolumesTpl()); + return cgogn::make_unique(instance_.get()); +} + + +using ShaderExplodeVolumes = ShaderExplodeVolumesTpl; +using ShaderExplodeVolumesColor = ShaderExplodeVolumesTpl; + + +#if !defined(CGOGN_RENDER_SHADERS_EXPLODE_VOLUME_CPP_) +extern template class CGOGN_RENDERING_API ShaderExplodeVolumesTpl; +extern template class CGOGN_RENDERING_API ShaderExplodeVolumesTpl; +extern template class CGOGN_RENDERING_API ShaderParamExplodeVolumes; +extern template class CGOGN_RENDERING_API ShaderParamExplodeVolumes; +#endif + } // namespace rendering } // namespace cgogn -#endif // RENDERING_SHADERS_EXPLODE_VOLUMES_H_ +#endif // CGOGN_RENDERING_SHADERS_EXPLODE_VOLUMES_H_ diff --git a/cgogn/rendering/shaders/shader_explode_volumes_line.cpp b/cgogn/rendering/shaders/shader_explode_volumes_line.cpp index a5e3c038..4a0de39d 100644 --- a/cgogn/rendering/shaders/shader_explode_volumes_line.cpp +++ b/cgogn/rendering/shaders/shader_explode_volumes_line.cpp @@ -23,10 +23,12 @@ #define CGOGN_RENDERING_DLL_EXPORT -#include +#include + +#include + #include #include -#include namespace cgogn { @@ -34,6 +36,15 @@ namespace cgogn namespace rendering { +std::unique_ptr ShaderExplodeVolumesLine::instance_ = nullptr; + +std::unique_ptr ShaderExplodeVolumesLine::generate_param() +{ + if (!instance_) + instance_ = std::unique_ptr(new ShaderExplodeVolumesLine()); + return cgogn::make_unique(instance_.get()); +} + const char* ShaderExplodeVolumesLine::vertex_shader_source_ = "#version 150\n" "in vec3 vertex_pos;\n" @@ -64,7 +75,6 @@ const char* ShaderExplodeVolumesLine::geometry_shader_source_ = " }\n" "}\n"; - const char* ShaderExplodeVolumesLine::fragment_shader_source_ = "#version 150\n" "uniform vec4 color;\n" @@ -73,7 +83,6 @@ const char* ShaderExplodeVolumesLine::fragment_shader_source_ = " fragColor = color;\n" "}\n"; - ShaderExplodeVolumesLine::ShaderExplodeVolumesLine() { prg_.addShaderFromSourceCode(QOpenGLShader::Vertex, vertex_shader_source_); @@ -86,57 +95,30 @@ ShaderExplodeVolumesLine::ShaderExplodeVolumesLine() unif_plane_clip_ = prg_.uniformLocation("plane_clip"); unif_color_ = prg_.uniformLocation("color"); - //default param + // default param bind(); set_explode_volume(0.8f); - set_color(QColor(255,255,255)); - set_plane_clip(QVector4D(0,0,0,0)); + set_color(QColor(255, 255, 255)); + set_plane_clip(QVector4D(0, 0, 0, 0)); release(); } void ShaderExplodeVolumesLine::set_color(const QColor& rgb) { - if (unif_color_>=0) - prg_.setUniformValue(unif_color_,rgb); + if (unif_color_ >= 0) + prg_.setUniformValue(unif_color_, rgb); } - void ShaderExplodeVolumesLine::set_explode_volume(float32 x) { - prg_.setUniformValue(unif_expl_v_, x); + prg_.setUniformValue(unif_expl_v_, x); } void ShaderExplodeVolumesLine::set_plane_clip(const QVector4D& plane) { - prg_.setUniformValue(unif_plane_clip_, plane); } -bool ShaderExplodeVolumesLine::set_vao(uint32 i, VBO* vbo_pos) -{ - if (i >= vaos_.size()) - { - cgogn_log_warning("set_vao") << "VAO number " << i << " does not exist."; - return false; - } - - QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); - - prg_.bind(); - vaos_[i]->bind(); - - // position vbo - vbo_pos->bind(); - ogl->glEnableVertexAttribArray(ATTRIB_POS); - ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); - vbo_pos->release(); - - vaos_[i]->release(); - prg_.release(); - - return true; -} - } // namespace rendering } // namespace cgogn diff --git a/cgogn/rendering/shaders/shader_explode_volumes_line.h b/cgogn/rendering/shaders/shader_explode_volumes_line.h index bc31708c..fe9d7106 100644 --- a/cgogn/rendering/shaders/shader_explode_volumes_line.h +++ b/cgogn/rendering/shaders/shader_explode_volumes_line.h @@ -21,14 +21,17 @@ * * *******************************************************************************/ -#ifndef RENDERING_SHADERS_EXPLODE_VOLUMES_LINE_H_ -#define RENDERING_SHADERS_EXPLODE_VOLUMES_LINE_H_ +#ifndef CGOGN_RENDERING_SHADERS_EXPLODE_VOLUMES_LINE_H_ +#define CGOGN_RENDERING_SHADERS_EXPLODE_VOLUMES_LINE_H_ +#include +#include +#include + +#include #include #include -#include -#include -#include +#include namespace cgogn { @@ -36,44 +39,86 @@ namespace cgogn namespace rendering { +// forward +class ShaderParamExplodeVolumesLine; + class CGOGN_RENDERING_API ShaderExplodeVolumesLine : public ShaderProgram { + friend class ShaderParamExplodeVolumesLine; + +protected: + static const char* vertex_shader_source_; static const char* geometry_shader_source_; static const char* fragment_shader_source_; + // uniform ids + GLint unif_expl_v_; + GLint unif_plane_clip_; + GLint unif_color_; + +public: + enum { ATTRIB_POS = 0, }; - // uniform ids - GLint unif_expl_v_; - GLint unif_plane_clip_; - GLint unif_color_; + using Param = ShaderParamExplodeVolumesLine; + static std::unique_ptr generate_param(); + void set_explode_volume(float32 x); + void set_plane_clip(const QVector4D& plane); + void set_color(const QColor& rgb); -public: +protected: ShaderExplodeVolumesLine(); + static std::unique_ptr instance_; +}; - void set_explode_volume(float32 x); +class CGOGN_RENDERING_API ShaderParamExplodeVolumesLine : public ShaderParam +{ +protected: - void set_plane_clip(const QVector4D& plane); + inline void set_uniforms() override + { + ShaderExplodeVolumesLine* sh = static_cast(this->shader_); + sh->set_color(color_); + sh->set_explode_volume(explode_factor_); + sh->set_plane_clip(plane_clip_); + } - void set_color(const QColor& rgb); +public: + + QColor color_; + QVector4D plane_clip_; + float32 explode_factor_; - /** - * @brief set a vao configuration - * @param i vao id (0,1,...) - * @param vbo_pos pointer on position vbo (XYZ) - * @return true if ok - */ - bool set_vao(uint32 i, VBO* vbo_pos); + ShaderParamExplodeVolumesLine(ShaderExplodeVolumesLine* sh) : + ShaderParam(sh), + color_(255, 255, 255), + plane_clip_(0, 0, 0, 0), + explode_factor_(0.8f) + {} + + void set_position_vbo(VBO* vbo_pos) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderExplodeVolumesLine::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderExplodeVolumesLine::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + vao_->release(); + shader_->release(); + } }; + } // namespace rendering } // namespace cgogn -#endif // RENDERING_SHADERS_EXPLODE_VOLUMES_LINE_H_ +#endif // CGOGN_RENDERING_SHADERS_EXPLODE_VOLUMES_LINE_H_ diff --git a/cgogn/rendering/shaders/shader_flat.cpp b/cgogn/rendering/shaders/shader_flat.cpp index 9885f970..486c8571 100644 --- a/cgogn/rendering/shaders/shader_flat.cpp +++ b/cgogn/rendering/shaders/shader_flat.cpp @@ -22,86 +22,87 @@ *******************************************************************************/ #define CGOGN_RENDERING_DLL_EXPORT +#define CGOGN_RENDER_SHADERS_FLAT_CPP_ -#include -#include -#include #include +#include + + namespace cgogn { namespace rendering { -const char* ShaderFlat::vertex_shader_source_ = - "#version 150\n" - "in vec3 vertex_pos;\n" - "uniform mat4 projection_matrix;\n" - "uniform mat4 model_view_matrix;\n" - "out vec3 pos;\n" - "void main() {\n" - " vec4 pos4 = model_view_matrix * vec4(vertex_pos,1.0);\n" - " pos = pos4.xyz;" - " gl_Position = projection_matrix * pos4;\n" - "}\n"; - -const char* ShaderFlat::fragment_shader_source_ = - "#version 150\n" - "out vec4 fragColor;\n" - "uniform vec4 front_color;\n" - "uniform vec4 back_color;\n" - "uniform vec4 ambiant_color;\n" - "uniform vec3 lightPosition;\n" - "in vec3 pos;\n" - "void main() {\n" - " vec3 N = normalize(cross(dFdx(pos),dFdy(pos)));\n" - " vec3 L = normalize(lightPosition-pos);\n" - " float lambert = dot(N,L);\n" - " if (gl_FrontFacing)\n" - " fragColor = ambiant_color+lambert*front_color;\n" - " else\n" - " fragColor = ambiant_color+lambert*back_color;\n" - "}\n"; - - -const char* ShaderFlat::vertex_shader_source2_ = - "#version 150\n" - "in vec3 vertex_pos;\n" - "in vec3 vertex_col;\n" - "uniform mat4 projection_matrix;\n" - "uniform mat4 model_view_matrix;\n" - "out vec3 pos;\n" - "out vec3 col;\n" - "void main() {\n" - " vec4 pos4 = model_view_matrix * vec4(vertex_pos,1.0);\n" - " pos = pos4.xyz;\n" - " col = vertex_col;\n" - " gl_Position = projection_matrix * pos4;\n" - "}\n"; - -const char* ShaderFlat::fragment_shader_source2_ = - "#version 150\n" - "out vec4 fragColor;\n" - "uniform vec4 front_color;\n" - "uniform vec4 back_color;\n" - "uniform vec4 ambiant_color;\n" - "uniform vec3 lightPosition;\n" - "in vec3 pos;\n" - "in vec3 col;\n" - "void main() {\n" - " vec3 N = normalize(cross(dFdx(pos),dFdy(pos)));\n" - " vec3 L = normalize(lightPosition-pos);\n" - " float lambert = dot(N,L);\n" - " if (gl_FrontFacing)\n" - " fragColor = ambiant_color+vec4(lambert*col,1.0);\n" - " else\n" - " fragColor = ambiant_color-vec4(lambert*col,1.0);\n" - "}\n"; - - -ShaderFlat::ShaderFlat(bool color_per_vertex) +const char* ShaderFlatGen::vertex_shader_source_ = +"#version 150\n" +"in vec3 vertex_pos;\n" +"uniform mat4 projection_matrix;\n" +"uniform mat4 model_view_matrix;\n" +"out vec3 pos;\n" +"void main() {\n" +" vec4 pos4 = model_view_matrix * vec4(vertex_pos,1.0);\n" +" pos = pos4.xyz;" +" gl_Position = projection_matrix * pos4;\n" +"}\n"; + +const char* ShaderFlatGen::fragment_shader_source_ = +"#version 150\n" +"out vec4 fragColor;\n" +"uniform vec4 front_color;\n" +"uniform vec4 back_color;\n" +"uniform vec4 ambiant_color;\n" +"uniform vec3 lightPosition;\n" +"in vec3 pos;\n" +"void main() {\n" +" vec3 N = normalize(cross(dFdx(pos),dFdy(pos)));\n" +" vec3 L = normalize(lightPosition-pos);\n" +" float lambert = dot(N,L);\n" +" if (gl_FrontFacing)\n" +" fragColor = ambiant_color+lambert*front_color;\n" +" else\n" +" fragColor = ambiant_color+lambert*back_color;\n" +"}\n"; + +const char* ShaderFlatGen::vertex_shader_source2_ = +"#version 150\n" +"in vec3 vertex_pos;\n" +"in vec3 vertex_col;\n" +"uniform mat4 projection_matrix;\n" +"uniform mat4 model_view_matrix;\n" +"out vec3 pos;\n" +"out vec3 col;\n" +"void main() {\n" +" vec4 pos4 = model_view_matrix * vec4(vertex_pos,1.0);\n" +" pos = pos4.xyz;\n" +" col = vertex_col;\n" +" gl_Position = projection_matrix * pos4;\n" +"}\n"; + +const char* ShaderFlatGen::fragment_shader_source2_ = +"#version 150\n" +"out vec4 fragColor;\n" +"uniform vec4 front_color;\n" +"uniform vec4 back_color;\n" +"uniform vec4 ambiant_color;\n" +"uniform vec3 lightPosition;\n" +"in vec3 pos;\n" +"in vec3 col;\n" +"void main() {\n" +" vec3 N = normalize(cross(dFdx(pos),dFdy(pos)));\n" +" vec3 L = normalize(lightPosition-pos);\n" +" float lambert = dot(N,L);\n" +" if (gl_FrontFacing)\n" +" fragColor = ambiant_color+vec4(lambert*col,1.0);\n" +" else\n" +" fragColor = ambiant_color-vec4(lambert*col,1.0);\n" +"}\n"; + + + +ShaderFlatGen::ShaderFlatGen(bool color_per_vertex) { if (color_per_vertex) { @@ -124,78 +125,40 @@ ShaderFlat::ShaderFlat(bool color_per_vertex) unif_back_color_ = prg_.uniformLocation("back_color"); unif_ambiant_color_ = prg_.uniformLocation("ambiant_color"); unif_light_position_ = prg_.uniformLocation("lightPosition"); - - //default param - bind(); - set_light_position(QVector3D(10.0f,100.0f,1000.0f)); - set_front_color(QColor(250,0,0)); - set_back_color(QColor(0,250,5)); - set_ambiant_color(QColor(5,5,5)); - release(); } -void ShaderFlat::set_light_position(const QVector3D& l) +void ShaderFlatGen::set_light_position(const QVector3D& l) { - prg_.setUniformValue(unif_light_position_,l); + prg_.setUniformValue(unif_light_position_, l); } -void ShaderFlat::set_local_light_position(const QVector3D& l, const QMatrix4x4& view_matrix) +void ShaderFlatGen::set_local_light_position(const QVector3D& l, const QMatrix4x4& view_matrix) { - QVector4D loc4 = view_matrix.map(QVector4D(l,1.0)); - prg_.setUniformValue(unif_light_position_, QVector3D(loc4)/loc4.w()); + QVector4D loc4 = view_matrix.map(QVector4D(l, 1.0)); + prg_.setUniformValue(unif_light_position_, QVector3D(loc4) / loc4.w()); } -void ShaderFlat::set_front_color(const QColor& rgb) +void ShaderFlatGen::set_front_color(const QColor& rgb) { - if (unif_front_color_>=0) - prg_.setUniformValue(unif_front_color_,rgb); + if (unif_front_color_ >= 0) + prg_.setUniformValue(unif_front_color_, rgb); } -void ShaderFlat::set_back_color(const QColor& rgb) +void ShaderFlatGen::set_back_color(const QColor& rgb) { - if (unif_back_color_>=0) - prg_.setUniformValue(unif_back_color_,rgb); + if (unif_back_color_ >= 0) + prg_.setUniformValue(unif_back_color_, rgb); } -void ShaderFlat::set_ambiant_color(const QColor& rgb) +void ShaderFlatGen::set_ambiant_color(const QColor& rgb) { - prg_.setUniformValue(unif_ambiant_color_,rgb); + prg_.setUniformValue(unif_ambiant_color_, rgb); } - -bool ShaderFlat::set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_color) -{ - if (i >= vaos_.size()) - { - cgogn_log_warning("set_vao") << "VAO number " << i << " does not exist."; - return false; - } - - QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); - - prg_.bind(); - vaos_[i]->bind(); - - // position vbo - vbo_pos->bind(); - ogl->glEnableVertexAttribArray(ATTRIB_POS); - ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); - vbo_pos->release(); - - if (vbo_color) - { - // color vbo - vbo_color->bind(); - ogl->glEnableVertexAttribArray(ATTRIB_COLOR); - ogl->glVertexAttribPointer(ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); - vbo_color->release(); - } - - vaos_[i]->release(); - prg_.release(); - - return true; -} +template class CGOGN_RENDERING_API ShaderFlatTpl; +template class CGOGN_RENDERING_API ShaderFlatTpl; +template class CGOGN_RENDERING_API ShaderParamFlat; +template class CGOGN_RENDERING_API ShaderParamFlat; } // namespace rendering diff --git a/cgogn/rendering/shaders/shader_flat.h b/cgogn/rendering/shaders/shader_flat.h index 2b37bcc0..7114a022 100644 --- a/cgogn/rendering/shaders/shader_flat.h +++ b/cgogn/rendering/shaders/shader_flat.h @@ -21,14 +21,15 @@ * * *******************************************************************************/ -#ifndef RENDERING_SHADERS_FLAT_H_ -#define RENDERING_SHADERS_FLAT_H_ +#ifndef CGOGN_RENDERING_SHADERS_FLAT_H_ +#define CGOGN_RENDERING_SHADERS_FLAT_H_ -#include -#include -#include +#include +#include +#include -class QColor; +#include +#include namespace cgogn { @@ -36,20 +37,23 @@ namespace cgogn namespace rendering { -class CGOGN_RENDERING_API ShaderFlat : public ShaderProgram +// forward +template +class ShaderParamFlat: public ShaderParam +{}; + +class CGOGN_RENDERING_API ShaderFlatGen : public ShaderProgram { + template friend class ShaderParamFlat; + +protected: + static const char* vertex_shader_source_; static const char* fragment_shader_source_; static const char* vertex_shader_source2_; static const char* fragment_shader_source2_; - enum - { - ATTRIB_POS = 0, - ATTRIB_COLOR - }; - // uniform ids GLint unif_front_color_; GLint unif_back_color_; @@ -58,7 +62,14 @@ class CGOGN_RENDERING_API ShaderFlat : public ShaderProgram public: - ShaderFlat(bool color_per_vertex = false); + using Self = ShaderFlatGen; + CGOGN_NOT_COPYABLE_NOR_MOVABLE(ShaderFlatGen); + + enum + { + ATTRIB_POS = 0, + ATTRIB_COLOR + }; /** * @brief set current front color @@ -84,7 +95,6 @@ class CGOGN_RENDERING_API ShaderFlat : public ShaderProgram */ void set_light_position(const QVector3D& l); - /** * @brief set light position relative to world * @param l light position @@ -92,19 +102,165 @@ class CGOGN_RENDERING_API ShaderFlat : public ShaderProgram */ void set_local_light_position(const QVector3D& l, const QMatrix4x4& view_matrix); - /** - * @brief set a vao configuration - * @param i id of vao (0,1,....) - * @param vbo_pos pointer on position vbo (XYZ) - * @param vbo_color pointer on color vbo (RGB) - * @return true if ok - */ - bool set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_col = NULL); +protected: + + ShaderFlatGen(bool color_per_vertex); +}; + +template +class ShaderFlatTpl : public ShaderFlatGen +{ +public: + + using Param = ShaderParamFlat; + static std::unique_ptr generate_param(); + +private: + + ShaderFlatTpl() : ShaderFlatGen(CPV) {} + static std::unique_ptr instance_; +}; + +template +std::unique_ptr> ShaderFlatTpl::instance_ = nullptr; + +// COLOR UNIFORM PARAM +template <> +class ShaderParamFlat : public ShaderParam +{ +protected: + + void set_uniforms() override + { + ShaderFlatGen* sh = static_cast(this->shader_); + sh->set_front_color(front_color_); + sh->set_back_color(back_color_); + sh->set_ambiant_color(ambiant_color_); + sh->set_light_position(light_pos_); + } + +public: + + QColor front_color_; + QColor back_color_; + QColor ambiant_color_; + QVector3D light_pos_; + + ShaderParamFlat(ShaderFlatTpl* sh) : + ShaderParam(sh), + front_color_(250, 0, 0), + back_color_(0, 250, 0), + ambiant_color_(5, 5, 5), + light_pos_(10, 100, 1000) + {} + + void set_position_vbo(VBO* vbo_pos) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + // position vbo + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderFlatGen::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderFlatGen::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + vao_->release(); + shader_->release(); + } }; + +// COLOR PER VERTEX PARAM +template <> +class ShaderParamFlat : public ShaderParam +{ +protected: + + void set_uniforms() override + { + ShaderFlatGen* sh = static_cast(this->shader_); + sh->set_ambiant_color(ambiant_color_); + sh->set_light_position(light_pos_); + } + +public: + + QColor ambiant_color_; + QVector3D light_pos_; + + ShaderParamFlat(ShaderFlatTpl* sh) : + ShaderParam(sh), + ambiant_color_(5, 5, 5), + light_pos_(10, 100, 1000) + {} + + void set_all_vbos(VBO* vbo_pos, VBO* vbo_color) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + // position + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderFlatGen::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderFlatGen::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + // color + vbo_color->bind(); + ogl->glEnableVertexAttribArray(ShaderFlatGen::ATTRIB_COLOR); + ogl->glVertexAttribPointer(ShaderFlatGen::ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_color->release(); + vao_->release(); + shader_->release(); + } + + void set_position_vbo(VBO* vbo_pos) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderFlatGen::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderFlatGen::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + vao_->release(); + shader_->release(); + } + + void set_color_vbo(VBO* vbo_color) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_color->bind(); + ogl->glEnableVertexAttribArray(ShaderFlatGen::ATTRIB_COLOR); + ogl->glVertexAttribPointer(ShaderFlatGen::ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_color->release(); + vao_->release(); + shader_->release(); + } +}; + +template +std::unique_ptr::Param> ShaderFlatTpl::generate_param() +{ + if (!instance_) + instance_ = std::unique_ptr>(new ShaderFlatTpl()); + return cgogn::make_unique(instance_.get()); +} + +using ShaderFlat = ShaderFlatTpl; +using ShaderFlatColor = ShaderFlatTpl; + +#if !defined(CGOGN_RENDER_SHADERS_FLAT_CPP_) +extern template class CGOGN_RENDERING_API ShaderFlatTpl; +extern template class CGOGN_RENDERING_API ShaderFlatTpl; +extern template class CGOGN_RENDERING_API ShaderParamFlat; +extern template class CGOGN_RENDERING_API ShaderParamFlat; +#endif + } // namespace rendering } // namespace cgogn -#endif // RENDERING_SHADERS_FLAT_H_ +#endif // CGOGN_RENDERING_SHADERS_FLAT_H_ diff --git a/cgogn/rendering/shaders/shader_phong.cpp b/cgogn/rendering/shaders/shader_phong.cpp index e0b3a435..b124b7fd 100644 --- a/cgogn/rendering/shaders/shader_phong.cpp +++ b/cgogn/rendering/shaders/shader_phong.cpp @@ -22,131 +22,129 @@ *******************************************************************************/ #define CGOGN_RENDERING_DLL_EXPORT +#define CGOGN_RENDER_SHADERS_PHONG_CPP_ -#include - -#include -#include #include +#include + namespace cgogn { namespace rendering { -const char* ShaderPhong::vertex_shader_source_ = - "#version 150\n" - "in vec3 vertex_pos;\n" - "in vec3 vertex_normal;\n" - "uniform mat4 projection_matrix;\n" - "uniform mat4 model_view_matrix;\n" - "uniform mat3 normal_matrix;\n" - "uniform vec3 lightPosition;\n" - "out vec3 EyeVector;\n" - "out vec3 Normal;\n" - "out vec3 LightDir;\n" - "void main ()\n" - "{\n" - " Normal = normal_matrix * vertex_normal;\n" - " vec3 Position = vec3 (model_view_matrix * vec4 (vertex_pos, 1.0));\n" - " LightDir = lightPosition - Position;\n" - " EyeVector = -Position;" - " gl_Position = projection_matrix * model_view_matrix * vec4 (vertex_pos, 1.0);\n" - "}\n"; - -const char* ShaderPhong::fragment_shader_source_ = - "#version 150\n" - "in vec3 EyeVector;\n" - "in vec3 Normal;\n" - "in vec3 LightDir;\n" - "uniform vec4 front_color;\n" - "uniform vec4 spec_color;\n" - "uniform vec4 ambiant_color;\n" - "uniform vec4 back_color;\n" - "uniform float spec_coef;\n" - "uniform bool double_side;\n" - "out vec4 frag_color;\n" - "void main()\n" - "{\n" - " vec3 N = normalize (Normal);\n" - " vec3 L = normalize (LightDir);\n" - " vec4 finalColor = ambiant_color;\n" - " vec4 currentColor = front_color;\n" - " if (!gl_FrontFacing)\n" - " {\n" - " if (!double_side)\n" - " discard;\n" - " N *= -1.0;\n" - " currentColor = back_color;\n" - " }\n" - " float lambertTerm = clamp(dot(N,L),0.0,1.0);\n" - " finalColor += currentColor*lambertTerm ;\n" - " vec3 E = normalize(EyeVector);\n" - " vec3 R = reflect(-L, N);\n" - " float specular = pow( max(dot(R, E), 0.0), spec_coef );\n" - " finalColor += spec_color * specular;\n" - " frag_color=finalColor;\n" - "}\n"; - - -const char* ShaderPhong::vertex_shader_source_2_ = - "#version 150\n" - "in vec3 vertex_pos;\n" - "in vec3 vertex_normal;\n" - "in vec3 vertex_color;\n" - "uniform mat4 projection_matrix;\n" - "uniform mat4 model_view_matrix;\n" - "uniform mat3 normal_matrix;\n" - "uniform vec3 lightPosition;\n" - "out vec3 EyeVector;\n" - "out vec3 Normal;\n" - "out vec3 LightDir;\n" - "out vec3 front_color;\n" - "void main ()\n" - "{\n" - " Normal = normal_matrix * vertex_normal;\n" - " vec3 Position = vec3 (model_view_matrix * vec4 (vertex_pos, 1.0));\n" - " LightDir = lightPosition - Position;\n" - " EyeVector = -Position;" - " front_color = vertex_color;" - " gl_Position = projection_matrix * model_view_matrix * vec4 (vertex_pos, 1.0);\n" - "}\n"; - -const char* ShaderPhong::fragment_shader_source_2_ = - "#version 150\n" - "in vec3 EyeVector;\n" - "in vec3 Normal;\n" - "in vec3 LightDir;\n" - "in vec3 front_color;\n" - "uniform vec4 spec_color;\n" - "uniform vec4 ambiant_color;\n" - "uniform float spec_coef;\n" - "uniform bool double_side;\n" - "out vec4 frag_color;\n" - "void main()\n" - "{\n" - " vec3 N = normalize (Normal);\n" - " vec3 L = normalize (LightDir);\n" - " vec4 finalColor = ambiant_color;\n" - " if (!gl_FrontFacing)\n" - " {\n" - " if (!double_side)\n" - " discard;\n" - " N *= -1.0;\n" - " }\n" - " float lambertTerm = clamp(dot(N,L),0.0,1.0);\n" - " finalColor += vec4(front_color*lambertTerm,0.0);\n" - " vec3 E = normalize(EyeVector);\n" - " vec3 R = reflect(-L, N);\n" - " float specular = pow( max(dot(R, E), 0.0), spec_coef );\n" - " finalColor += spec_color * specular;\n" - " frag_color=finalColor;\n" - "}\n"; - - - -ShaderPhong::ShaderPhong(bool color_per_vertex) +const char* ShaderPhongGen::vertex_shader_source_ = +"#version 150\n" +"in vec3 vertex_pos;\n" +"in vec3 vertex_normal;\n" +"uniform mat4 projection_matrix;\n" +"uniform mat4 model_view_matrix;\n" +"uniform mat3 normal_matrix;\n" +"uniform vec3 lightPosition;\n" +"out vec3 EyeVector;\n" +"out vec3 Normal;\n" +"out vec3 LightDir;\n" +"void main ()\n" +"{\n" +" Normal = normal_matrix * vertex_normal;\n" +" vec3 Position = vec3 (model_view_matrix * vec4 (vertex_pos, 1.0));\n" +" LightDir = lightPosition - Position;\n" +" EyeVector = -Position;" +" gl_Position = projection_matrix * model_view_matrix * vec4 (vertex_pos, 1.0);\n" +"}\n"; + +const char* ShaderPhongGen::fragment_shader_source_ = +"#version 150\n" +"in vec3 EyeVector;\n" +"in vec3 Normal;\n" +"in vec3 LightDir;\n" +"uniform vec4 front_color;\n" +"uniform vec4 spec_color;\n" +"uniform vec4 ambiant_color;\n" +"uniform vec4 back_color;\n" +"uniform float spec_coef;\n" +"uniform bool double_side;\n" +"out vec4 frag_color;\n" +"void main()\n" +"{\n" +" vec3 N = normalize (Normal);\n" +" vec3 L = normalize (LightDir);\n" +" vec4 finalColor = ambiant_color;\n" +" vec4 currentColor = front_color;\n" +" if (gl_FrontFacing==false)\n" // do not use ! because of bug on old intel under OS/X +" {\n" +" if (!double_side)\n" +" discard;\n" +" N *= -1.0;\n" +" currentColor = back_color;\n" +" }\n" +" float lambertTerm = clamp(dot(N,L),0.0,1.0);\n" +" finalColor += currentColor*lambertTerm ;\n" +" vec3 E = normalize(EyeVector);\n" +" vec3 R = reflect(-L, N);\n" +" float specular = pow( max(dot(R, E), 0.0), spec_coef );\n" +" finalColor += spec_color * specular;\n" +" frag_color=finalColor;\n" +"}\n"; + +const char* ShaderPhongGen::vertex_shader_source_2_ = +"#version 150\n" +"in vec3 vertex_pos;\n" +"in vec3 vertex_normal;\n" +"in vec3 vertex_color;\n" +"uniform mat4 projection_matrix;\n" +"uniform mat4 model_view_matrix;\n" +"uniform mat3 normal_matrix;\n" +"uniform vec3 lightPosition;\n" +"out vec3 EyeVector;\n" +"out vec3 Normal;\n" +"out vec3 LightDir;\n" +"out vec3 front_color;\n" +"void main ()\n" +"{\n" +" Normal = normal_matrix * vertex_normal;\n" +" vec3 Position = vec3 (model_view_matrix * vec4 (vertex_pos, 1.0));\n" +" LightDir = lightPosition - Position;\n" +" EyeVector = -Position;" +" front_color = vertex_color;" +" gl_Position = projection_matrix * model_view_matrix * vec4 (vertex_pos, 1.0);\n" +"}\n"; + +const char* ShaderPhongGen::fragment_shader_source_2_ = +"#version 150\n" +"in vec3 EyeVector;\n" +"in vec3 Normal;\n" +"in vec3 LightDir;\n" +"in vec3 front_color;\n" +"uniform vec4 spec_color;\n" +"uniform vec4 ambiant_color;\n" +"uniform float spec_coef;\n" +"uniform bool double_side;\n" +"out vec4 frag_color;\n" +"void main()\n" +"{\n" +" vec3 N = normalize (Normal);\n" +" vec3 L = normalize (LightDir);\n" +" vec4 finalColor = ambiant_color;\n" +" if (gl_FrontFacing==false)\n" // do not use ! because of bug on old intel under OS/X +" {\n" +" if (!double_side)\n" +" discard;\n" +" N *= -1.0;\n" +" }\n" +" float lambertTerm = clamp(dot(N,L),0.0,1.0);\n" +" finalColor += vec4(front_color*lambertTerm,0.0);\n" +" vec3 E = normalize(EyeVector);\n" +" vec3 R = reflect(-L, N);\n" +" float specular = pow( max(dot(R, E), 0.0), spec_coef );\n" +" finalColor += spec_color * specular;\n" +" frag_color=finalColor;\n" +"}\n"; + + + +ShaderPhongGen::ShaderPhongGen(bool color_per_vertex) { if (color_per_vertex) { @@ -167,6 +165,7 @@ ShaderPhong::ShaderPhong(bool color_per_vertex) prg_.link(); get_matrices_uniforms(); } + unif_front_color_ = prg_.uniformLocation("front_color"); unif_back_color_ = prg_.uniformLocation("back_color"); unif_ambiant_color_ = prg_.uniformLocation("ambiant_color"); @@ -177,101 +176,64 @@ ShaderPhong::ShaderPhong(bool color_per_vertex) //default param bind(); - set_light_position(QVector3D(10.0f,100.0f,1000.0f)); - set_front_color(QColor(250,0,0)); - set_back_color(QColor(0,250,5)); - set_ambiant_color(QColor(5,5,5)); - set_specular_color(QColor(100,100,100)); + set_light_position(QVector3D(10.0f, 100.0f, 1000.0f)); + set_front_color(QColor(250, 0, 0)); + set_back_color(QColor(0, 250, 5)); + set_ambiant_color(QColor(5, 5, 5)); + set_specular_color(QColor(100, 100, 100)); set_specular_coef(50.0f); set_double_side(true); release(); } -void ShaderPhong::set_light_position(const QVector3D& l) +void ShaderPhongGen::set_light_position(const QVector3D& l) { - prg_.setUniformValue(unif_light_position_,l); + prg_.setUniformValue(unif_light_position_, l); } -void ShaderPhong::set_local_light_position(const QVector3D& l, const QMatrix4x4& view_matrix) +void ShaderPhongGen::set_local_light_position(const QVector3D& l, const QMatrix4x4& view_matrix) { - QVector4D loc4 = view_matrix.map(QVector4D(l,1.0)); - prg_.setUniformValue(unif_light_position_, QVector3D(loc4)/loc4.w()); + QVector4D loc4 = view_matrix.map(QVector4D(l, 1.0)); + prg_.setUniformValue(unif_light_position_, QVector3D(loc4) / loc4.w()); } - -void ShaderPhong::set_front_color(const QColor& rgb) +void ShaderPhongGen::set_front_color(const QColor& rgb) { - if (unif_front_color_>=0) - prg_.setUniformValue(unif_front_color_,rgb); + if (unif_front_color_ >= 0) + prg_.setUniformValue(unif_front_color_, rgb); } -void ShaderPhong::set_back_color(const QColor& rgb) +void ShaderPhongGen::set_back_color(const QColor& rgb) { - if (unif_back_color_>=0) - prg_.setUniformValue(unif_back_color_,rgb); + if (unif_back_color_ >= 0) + prg_.setUniformValue(unif_back_color_, rgb); } -void ShaderPhong::set_ambiant_color(const QColor& rgb) +void ShaderPhongGen::set_ambiant_color(const QColor& rgb) { - prg_.setUniformValue(unif_ambiant_color_,rgb); + prg_.setUniformValue(unif_ambiant_color_, rgb); } -void ShaderPhong::set_specular_color(const QColor& rgb) +void ShaderPhongGen::set_specular_color(const QColor& rgb) { - prg_.setUniformValue(unif_spec_color_,rgb); + prg_.setUniformValue(unif_spec_color_, rgb); } -void ShaderPhong::set_specular_coef(float32 coef) +void ShaderPhongGen::set_specular_coef(float32 coef) { - prg_.setUniformValue(unif_spec_coef_,coef); + prg_.setUniformValue(unif_spec_coef_, coef); } -void ShaderPhong::set_double_side(bool ts) +void ShaderPhongGen::set_double_side(bool ts) { - prg_.setUniformValue(unif_double_side_,ts); + prg_.setUniformValue(unif_double_side_, ts); } -bool ShaderPhong::set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_norm, VBO* vbo_color) -{ - if (i >= vaos_.size()) - { - cgogn_log_warning("set_vao") << "VAO number " << i << " does not exist."; - return false; - } - - QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); - - prg_.bind(); - vaos_[i]->bind(); - - // position vbo - vbo_pos->bind(); - ogl->glEnableVertexAttribArray(ATTRIB_POS); - ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); - vbo_pos->release(); - - // normal vbo - vbo_norm->bind(); - ogl->glEnableVertexAttribArray(ATTRIB_NORM); - ogl->glVertexAttribPointer(ATTRIB_NORM, vbo_norm->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); - vbo_norm->release(); - - if (vbo_color) - { - // color vbo - vbo_color->bind(); - ogl->glEnableVertexAttribArray(ATTRIB_COLOR); - ogl->glVertexAttribPointer(ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); - vbo_color->release(); - } - - vaos_[i]->release(); - prg_.release(); - - return true; -} +template class CGOGN_RENDERING_API ShaderPhongTpl; +template class CGOGN_RENDERING_API ShaderPhongTpl; +template class CGOGN_RENDERING_API ShaderParamPhong; +template class CGOGN_RENDERING_API ShaderParamPhong; } // namespace rendering } // namespace cgogn - diff --git a/cgogn/rendering/shaders/shader_phong.h b/cgogn/rendering/shaders/shader_phong.h index 363526ca..2f6286ff 100644 --- a/cgogn/rendering/shaders/shader_phong.h +++ b/cgogn/rendering/shaders/shader_phong.h @@ -21,14 +21,16 @@ * * *******************************************************************************/ -#ifndef RENDERING_SHADERS_PHONG_H_ -#define RENDERING_SHADERS_PHONG_H_ +#ifndef CGOGN_RENDERING_SHADERS_PHONG_H_ +#define CGOGN_RENDERING_SHADERS_PHONG_H_ -#include -#include -#include +#include +#include +#include -class QColor; +#include +#include +#include namespace cgogn { @@ -36,22 +38,23 @@ namespace cgogn namespace rendering { -class CGOGN_RENDERING_API ShaderPhong : public ShaderProgram +// forward +template +class ShaderParamPhong: public ShaderParam +{}; + +class CGOGN_RENDERING_API ShaderPhongGen : public ShaderProgram { + template friend class ShaderParamPhong; + +protected: + static const char* vertex_shader_source_; static const char* fragment_shader_source_; static const char* vertex_shader_source_2_; static const char* fragment_shader_source_2_; - - enum - { - ATTRIB_POS = 0, - ATTRIB_NORM, - ATTRIB_COLOR - }; - // uniform ids GLint unif_front_color_; GLint unif_back_color_; @@ -63,7 +66,15 @@ class CGOGN_RENDERING_API ShaderPhong : public ShaderProgram public: - ShaderPhong(bool color_per_vertex = false); + using Self = ShaderPhongGen; + CGOGN_NOT_COPYABLE_NOR_MOVABLE(ShaderPhongGen); + + enum + { + ATTRIB_POS = 0, + ATTRIB_NORM, + ATTRIB_COLOR + }; /** * @brief set current front color @@ -114,19 +125,234 @@ class CGOGN_RENDERING_API ShaderPhong : public ShaderProgram */ void set_local_light_position(const QVector3D& l, const QMatrix4x4& view_matrix); - /** - * @brief set a vao configuration - * @param i id of vao (0,1,....) - * @param vbo_pos pointer on position vbo (XYZ) - * @param vbo_norm pointer on normal vbo (XYZ) - * @param vbo_color pointer on normal vbo (RGB) only used when color per vertex rendering - * @return true if ok - */ - bool set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_norm, VBO* vbo_color=NULL); +protected: + + ShaderPhongGen(bool color_per_vertex); }; + +template +class ShaderPhongTpl : public ShaderPhongGen +{ +public: + + using Param = ShaderParamPhong; + static std::unique_ptr generate_param(); + +private: + + ShaderPhongTpl() : ShaderPhongGen(CPV) {} + static std::unique_ptr instance_; +}; + +template +std::unique_ptr> ShaderPhongTpl::instance_ = nullptr; + + +// COLOR UNIFORM PARAM +template <> +class ShaderParamPhong : public ShaderParam +{ +protected: + + void set_uniforms() override + { + ShaderPhongGen* sh = static_cast(this->shader_); + sh->set_front_color(front_color_); + sh->set_back_color(back_color_); + sh->set_ambiant_color(ambiant_color_); + sh->set_specular_color(specular_color_); + sh->set_specular_coef(specular_coef_); + sh->set_double_side(double_side_); + sh->set_light_position(light_position_); + } + +public: + + QVector3D light_position_; + QColor front_color_; + QColor back_color_; + QColor ambiant_color_; + QColor specular_color_; + float32 specular_coef_; + bool double_side_; + + ShaderParamPhong(ShaderPhongTpl* sh) : + ShaderParam(sh), + light_position_(10.0f, 100.0f, 1000.0f), + front_color_(250, 0, 0), + back_color_(0, 250, 5), + ambiant_color_(5, 5, 5), + specular_color_(100, 100, 100), + specular_coef_(50.0f), + double_side_(true) + {} + + void set_all_vbos(VBO* vbo_pos, VBO* vbo_norm) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + // position vbo + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderPhongGen::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderPhongGen::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + // normal vbo + vbo_norm->bind(); + ogl->glEnableVertexAttribArray(ShaderPhongGen::ATTRIB_NORM); + ogl->glVertexAttribPointer(ShaderPhongGen::ATTRIB_NORM, vbo_norm->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_norm->release(); + vao_->release(); + shader_->release(); + } + + void set_position_vbo(VBO* vbo_pos) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderPhongGen::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderPhongGen::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + vao_->release(); + shader_->release(); + } + + void set_normal_vbo(VBO* vbo_norm) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_norm->bind(); + ogl->glEnableVertexAttribArray(ShaderPhongGen::ATTRIB_NORM); + ogl->glVertexAttribPointer(ShaderPhongGen::ATTRIB_NORM, vbo_norm->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_norm->release(); + vao_->release(); + shader_->release(); + } +}; + +// COLOR PER VERTEX PARAM +template <> +class ShaderParamPhong : public ShaderParam +{ +protected: + + void set_uniforms() override + { + ShaderPhongGen* sh = static_cast(this->shader_); + sh->set_ambiant_color(ambiant_color_); + sh->set_specular_color(specular_color_); + sh->set_specular_coef(specular_coef_); + sh->set_double_side(double_side_); + sh->set_light_position(light_position_); + } + +public: + + QVector3D light_position_; + QColor ambiant_color_; + QColor specular_color_; + float32 specular_coef_; + bool double_side_; + + ShaderParamPhong(ShaderPhongTpl* sh) : + ShaderParam(sh), + light_position_(10.0f, 100.0f, 1000.0f), + ambiant_color_(5, 5, 5), + specular_color_(100, 100, 100), + specular_coef_(50.0f), + double_side_(true) + {} + + void set_all_vbos(VBO* vbo_pos, VBO* vbo_norm, VBO* vbo_color) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + // position vbo + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderPhongGen::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderPhongGen::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + // normal vbo + vbo_norm->bind(); + ogl->glEnableVertexAttribArray(ShaderPhongGen::ATTRIB_NORM); + ogl->glVertexAttribPointer(ShaderPhongGen::ATTRIB_NORM, vbo_norm->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_norm->release(); + // color vbo + vbo_color->bind(); + ogl->glEnableVertexAttribArray(ShaderPhongGen::ATTRIB_COLOR); + ogl->glVertexAttribPointer(ShaderPhongGen::ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_color->release(); + vao_->release(); + shader_->release(); + } + + void set_position_vbo(VBO* vbo_pos) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderPhongGen::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderPhongGen::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + vao_->release(); + shader_->release(); + } + + void set_normal_vbo(VBO* vbo_norm) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_norm->bind(); + ogl->glEnableVertexAttribArray(ShaderPhongGen::ATTRIB_NORM); + ogl->glVertexAttribPointer(ShaderPhongGen::ATTRIB_NORM, vbo_norm->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_norm->release(); + vao_->release(); + shader_->release(); + } + + void set_color_vbo(VBO* vbo_color) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_color->bind(); + ogl->glEnableVertexAttribArray(ShaderPhongGen::ATTRIB_COLOR); + ogl->glVertexAttribPointer(ShaderPhongGen::ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_color->release(); + vao_->release(); + shader_->release(); + } +}; + + +template +std::unique_ptr::Param> ShaderPhongTpl::generate_param() +{ + if (!instance_) + instance_ = std::unique_ptr>(new ShaderPhongTpl); + return (cgogn::make_unique(instance_.get())); +} + + +using ShaderPhong = ShaderPhongTpl; +using ShaderPhongColor = ShaderPhongTpl; + + +#if !defined(CGOGN_RENDER_SHADERS_PHONG_CPP_) +extern template class CGOGN_RENDERING_API ShaderPhongTpl; +extern template class CGOGN_RENDERING_API ShaderPhongTpl; +extern template class CGOGN_RENDERING_API ShaderParamPhong; +extern template class CGOGN_RENDERING_API ShaderParamPhong; +#endif } // namespace rendering } // namespace cgogn -#endif // RENDERING_SHADERS_PHONG_H_ +#endif // CGOGN_RENDERING_SHADERS_PHONG_H_ diff --git a/cgogn/rendering/shaders/shader_point_sprite.cpp b/cgogn/rendering/shaders/shader_point_sprite.cpp index fd06be3f..7691e0bc 100644 --- a/cgogn/rendering/shaders/shader_point_sprite.cpp +++ b/cgogn/rendering/shaders/shader_point_sprite.cpp @@ -22,12 +22,14 @@ *******************************************************************************/ #define CGOGN_RENDERING_DLL_EXPORT +#define CGOGN_RENDER_SHADERS_POINT_SPRITE_CPP_ -#include +#include + +#include #include #include -#include namespace cgogn { @@ -35,76 +37,7 @@ namespace cgogn namespace rendering { -const char* ShaderPointSprite::vertex_shader_source_ = -"#version 150\n" -"in vec3 vertex_pos;\n" -"void main() {\n" -" gl_Position = vec4(vertex_pos,1.0);\n" -"}\n"; - - -const char* ShaderPointSprite::geometry_shader_source_ = -"#version 150\n" -"layout (points) in;\n" -"layout (triangle_strip, max_vertices=4) out;\n" -"uniform mat4 projection_matrix;\n" -"uniform mat4 model_view_matrix;\n" -"uniform float point_size;\n" -"out vec2 spriteCoord;\n" -"out vec3 sphereCenter;\n" -"void corner(vec4 center, float x, float y)\n" -"{\n" -" spriteCoord = vec2(x,y);\n" -" vec4 pos = center + vec4(point_size*x, point_size*y, 0.0, 0.0);\n" -" gl_Position = projection_matrix * pos;\n" -" EmitVertex();\n" -"}\n" -"void main()\n" -"{\n" - -" vec4 posCenter = model_view_matrix * gl_in[0].gl_Position;\n" -" sphereCenter = posCenter.xyz;\n" -" corner(posCenter, -1.4, 1.4);\n" -" corner(posCenter, -1.4,-1.4);\n" -" corner(posCenter, 1.4, 1.4);\n" -" corner(posCenter, 1.4,-1.4);\n" -" EndPrimitive();\n" -"}\n"; - - -const char* ShaderPointSprite::fragment_shader_source_ = -"#version 150\n" -"uniform mat4 projection_matrix;\n" -"uniform vec4 color;\n" -"uniform vec4 ambiant;\n" -"uniform vec3 lightPos;\n" -"uniform float point_size;\n" -"in vec2 spriteCoord;\n" -"in vec3 sphereCenter;\n" -"out vec3 fragColor;\n" -"void main() {\n" -" vec3 billboard_frag_pos = sphereCenter + vec3(spriteCoord, 0.0) * point_size;\n" -" vec3 ray_direction = normalize(billboard_frag_pos);\n" -" float TD = -dot(ray_direction,sphereCenter);\n" -" float c = dot(sphereCenter, sphereCenter) - point_size * point_size;\n" -" float arg = TD * TD - c;\n" -" if (arg < 0.0)\n" -" discard;\n" -" float t = -c / (TD - sqrt(arg));\n" -" vec3 frag_position_eye = ray_direction * t ;\n" -" vec4 pos = projection_matrix * vec4(frag_position_eye, 1.0);\n" -" gl_FragDepth = (pos.z / pos.w + 1.0) / 2.0;\n" -" vec3 N = normalize(frag_position_eye - sphereCenter);\n" -" vec3 L = normalize (lightPos - frag_position_eye);\n" -" float lambertTerm = dot(N,L);\n" -" vec4 result = color*lambertTerm;\n" -" result += ambiant;\n" -" fragColor = result.rgb;\n" -"}\n"; - - - -const char* ShaderPointSprite::vertex_shader_source2_ = +const char* ShaderPointSpriteGen::vertex_shader_source_ = "in vec3 vertex_pos;\n" "#if WITH_COLOR == 1\n" "in vec3 vertex_col;\n" @@ -124,8 +57,7 @@ const char* ShaderPointSprite::vertex_shader_source2_ = " gl_Position = vec4(vertex_pos,1.0);\n" "}\n"; - -const char* ShaderPointSprite::geometry_shader_source2_ = +const char* ShaderPointSpriteGen::geometry_shader_source_ = "layout (points) in;\n" "layout (triangle_strip, max_vertices=4) out;\n" "uniform mat4 projection_matrix;\n" @@ -188,7 +120,6 @@ const char* ShaderPointSprite::geometry_shader_source2_ = "#endif\n" "void main()\n" "{\n" - " vec4 posCenter = model_view_matrix * gl_in[0].gl_Position;\n" " sphereCenter = posCenter.xyz;\n" " corner(posCenter, -1.4, 1.4);\n" @@ -198,8 +129,7 @@ const char* ShaderPointSprite::geometry_shader_source2_ = " EndPrimitive();\n" "}\n"; - -const char* ShaderPointSprite::fragment_shader_source2_ = +const char* ShaderPointSpriteGen::fragment_shader_source_ = "uniform mat4 projection_matrix;\n" "uniform vec4 ambiant;\n" "uniform vec3 lightPos;\n" @@ -244,15 +174,12 @@ const char* ShaderPointSprite::fragment_shader_source2_ = " fragColor = result.rgb;\n" "}\n"; - - - - -ShaderPointSprite::ShaderPointSprite(bool color_per_vertex, bool size_per_vertex) +ShaderPointSpriteGen::ShaderPointSpriteGen(bool color_per_vertex, bool size_per_vertex) { std::string vs("#version 150\n"); std::string fs("#version 150\n"); std::string gs("#version 150\n"); + if (color_per_vertex) { vs += std::string("#define WITH_COLOR 1\n"); @@ -279,10 +206,9 @@ ShaderPointSprite::ShaderPointSprite(bool color_per_vertex, bool size_per_vertex fs += std::string("#define WITH_SIZE 0\n"); } - vs += std::string(vertex_shader_source2_); - gs += std::string(geometry_shader_source2_); - fs += std::string(fragment_shader_source2_); - + vs += std::string(vertex_shader_source_); + gs += std::string(geometry_shader_source_); + fs += std::string(fragment_shader_source_); prg_.addShaderFromSourceCode(QOpenGLShader::Vertex, vs.c_str()); prg_.addShaderFromSourceCode(QOpenGLShader::Geometry, gs.c_str()); @@ -298,105 +224,77 @@ ShaderPointSprite::ShaderPointSprite(bool color_per_vertex, bool size_per_vertex prg_.link(); get_matrices_uniforms(); -// } -// else -// { -// prg_.addShaderFromSourceCode(QOpenGLShader::Vertex, vertex_shader_source2_); -// prg_.addShaderFromSourceCode(QOpenGLShader::Geometry, geometry_shader_source2_); -// prg_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader_source2_); -// prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); -// prg_.link(); - -// get_matrices_uniforms(); -// } unif_color_ = prg_.uniformLocation("color"); unif_ambiant_ = prg_.uniformLocation("ambiant"); unif_light_pos_ = prg_.uniformLocation("lightPos"); unif_size_ = prg_.uniformLocation("point_size"); + if (!color_per_vertex) + set_color(QColor(250, 0, 0)); - set_color(QColor(250,0,0)); - set_ambiant(QColor(5,5,5)); - set_size(1.0f); - set_light_position(QVector3D(10,10,1000)); -} + set_ambiant(QColor(5, 5, 5)); + if (!size_per_vertex) + set_size(1.0f); + set_light_position(QVector3D(10, 10, 1000)); +} -void ShaderPointSprite::set_color(const QColor& rgb) +void ShaderPointSpriteGen::set_color(const QColor& rgb) { - if (unif_color_>=0) + if (unif_color_ >= 0) prg_.setUniformValue(unif_color_, rgb); } -void ShaderPointSprite::set_ambiant(const QColor& rgb) +/** +* @brief set ambiant color +* @param rgb +*/ +void ShaderPointSpriteGen::set_ambiant(const QColor& rgb) { - if (unif_ambiant_>=0) + if (unif_ambiant_ >= 0) prg_.setUniformValue(unif_ambiant_, rgb); } -void ShaderPointSprite::set_size(float32 w) +/** +* @brief set light position relative to screen +* @param l +*/ +void ShaderPointSpriteGen::set_light_position(const QVector3D& l) { -// if (unif_size_>=0) - prg_.setUniformValue(unif_size_, w); + prg_.setUniformValue(unif_light_pos_, l); } -void ShaderPointSprite::set_light_position(const QVector3D& l) +/** +* @brief set light position relative to world +* @param l +* @param view_matrix +*/ +void ShaderPointSpriteGen::set_local_light_position(const QVector3D& l, const QMatrix4x4& view_matrix) { - prg_.setUniformValue(unif_light_pos_,l); + QVector4D loc4 = view_matrix.map(QVector4D(l, 1.0)); + prg_.setUniformValue(unif_light_pos_, QVector3D(loc4) / loc4.w()); } -void ShaderPointSprite::set_local_light_position(const QVector3D& l, const QMatrix4x4& view_matrix) +/** +* @brief set the size of sphere (call before each draw) +* @param w size ofs phere +*/ +// template ::type* = nullptr> +void ShaderPointSpriteGen::set_size(float32 w) { - QVector4D loc4 = view_matrix.map(QVector4D(l,1.0)); - prg_.setUniformValue(unif_light_pos_, QVector3D(loc4)/loc4.w()); + if (unif_size_ >= 0) + prg_.setUniformValue(unif_size_, w); } - - -bool ShaderPointSprite::set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_color, VBO* vbo_size) -{ - if (i >= vaos_.size()) - { - cgogn_log_warning("set_vao") << "VAO number " << i << " does not exist."; - return false; - } - - QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); - - prg_.bind(); - vaos_[i]->bind(); - - // position vbo - vbo_pos->bind(); - ogl->glEnableVertexAttribArray(ATTRIB_POS); - ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); - vbo_pos->release(); - - if (vbo_color) - { - // color vbo - vbo_color->bind(); - ogl->glEnableVertexAttribArray(ATTRIB_COLOR); - ogl->glVertexAttribPointer(ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); - vbo_color->release(); - } - - if (vbo_size) - { - // size vbo - vbo_size->bind(); - ogl->glEnableVertexAttribArray(ATTRIB_SIZE); - ogl->glVertexAttribPointer(ATTRIB_SIZE, vbo_size->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); - vbo_size->release(); - } - - - vaos_[i]->release(); - prg_.release(); - - return true; -} +template class CGOGN_RENDERING_API ShaderPointSpriteTpl; +template class CGOGN_RENDERING_API ShaderPointSpriteTpl; +template class CGOGN_RENDERING_API ShaderPointSpriteTpl; +template class CGOGN_RENDERING_API ShaderPointSpriteTpl; +template class CGOGN_RENDERING_API ShaderParamPointSprite; +template class CGOGN_RENDERING_API ShaderParamPointSprite; +template class CGOGN_RENDERING_API ShaderParamPointSprite; +template class CGOGN_RENDERING_API ShaderParamPointSprite; } // namespace rendering diff --git a/cgogn/rendering/shaders/shader_point_sprite.h b/cgogn/rendering/shaders/shader_point_sprite.h index 84892539..e7276ca5 100644 --- a/cgogn/rendering/shaders/shader_point_sprite.h +++ b/cgogn/rendering/shaders/shader_point_sprite.h @@ -21,12 +21,18 @@ * * *******************************************************************************/ -#ifndef RENDERING_SHADER_POINT_SPRITE_H_ -#define RENDERING_SHADER_POINT_SPRITE_H_ +#ifndef CGOGN_RENDERING_SHADER_POINT_SPRITE_H_ +#define CGOGN_RENDERING_SHADER_POINT_SPRITE_H_ -#include -#include -#include +#include +#include +#include + +#include +#include +#include + +#include namespace cgogn { @@ -34,23 +40,21 @@ namespace cgogn namespace rendering { -class CGOGN_RENDERING_API ShaderPointSprite : public ShaderProgram +// forward +template +class ShaderParamPointSprite : public ShaderParam +{}; + +class CGOGN_RENDERING_API ShaderPointSpriteGen : public ShaderProgram { + template friend class ShaderParamPointSprite; + +protected: + static const char* vertex_shader_source_; static const char* geometry_shader_source_; static const char* fragment_shader_source_; - static const char* vertex_shader_source2_; - static const char* geometry_shader_source2_; - static const char* fragment_shader_source2_; - - enum - { - ATTRIB_POS = 0, - ATTRIB_COLOR, - ATTRIB_SIZE - }; - // uniform ids GLint unif_color_; GLint unif_size_; @@ -59,54 +63,370 @@ class CGOGN_RENDERING_API ShaderPointSprite : public ShaderProgram public: - ShaderPointSprite(bool color_per_vertex = false, bool size_per_vertex = false); + using Self = ShaderPointSpriteGen; + CGOGN_NOT_COPYABLE_NOR_MOVABLE(ShaderPointSpriteGen); + + enum + { + ATTRIB_POS = 0, + ATTRIB_COLOR, + ATTRIB_SIZE + }; - /** - * @brief set current color - * @param rgb - */ void set_color(const QColor& rgb); /** - * @brief set ambiant color - * @param rgb - */ + * @brief set ambiant color + * @param rgb + */ void set_ambiant(const QColor& rgb); /** - * @brief set light position relative to screen - * @param l - */ + * @brief set light position relative to screen + * @param l + */ void set_light_position(const QVector3D& l); /** - * @brief set light position relative to world - * @param l - * @param view_matrix - */ + * @brief set light position relative to world + * @param l + * @param view_matrix + */ void set_local_light_position(const QVector3D& l, const QMatrix4x4& view_matrix); - - /** - * @brief set the size of sphere (call before each draw) - * @param w size ofs phere - */ + * @brief set the size of sphere (call before each draw) + * @param w size ofs phere + */ void set_size(float32 w); - /** - * @brief set a vao configuration - * @param i vao id (0,1,...) - * @param vbo_pos pointer on position vbo (XYZ) - * @param vbo_color pointer on color vbo - * @param vbo_size pointer on size (diameters of spheres) vbo - * @return true if ok - */ - bool set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_color=NULL, VBO* vbo_size=NULL); +protected: + + ShaderPointSpriteGen(bool color_per_vertex, bool size_per_vertex); +}; + +template +class ShaderPointSpriteTpl : public ShaderPointSpriteGen +{ +public: + + using Param = ShaderParamPointSprite; + static std::unique_ptr generate_param(); + +private: + + ShaderPointSpriteTpl() : ShaderPointSpriteGen(CPV, SPV) {} + static std::unique_ptr instance_; +}; + + +template +std::unique_ptr> ShaderPointSpriteTpl::instance_ = nullptr; + + +template <> +class ShaderParamPointSprite : public ShaderParam +{ +protected: + + void set_uniforms() override + { + ShaderPointSpriteGen* sh = static_cast(this->shader_); + sh->set_color(color_); + sh->set_size(size_); + sh->set_ambiant(ambiant_color_); + sh->set_light_position(light_pos_); + } + +public: + + QColor color_; + QColor ambiant_color_; + QVector3D light_pos_; + float32 size_; + + ShaderParamPointSprite(ShaderPointSpriteTpl* sh) : + ShaderParam(sh), + color_(0, 0, 255), + ambiant_color_(5, 5, 5), + light_pos_(10, 100, 1000), + size_(1.0) + {} + + void set_position_vbo(VBO* vbo_pos) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderPointSpriteGen::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderPointSpriteGen::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + vao_->release(); + shader_->release(); + } +}; + +template <> +class ShaderParamPointSprite : public ShaderParam +{ +protected: + + void set_uniforms() override + { + ShaderPointSpriteGen* sh = static_cast(this->shader_); + sh->set_color(color_); + sh->set_ambiant(ambiant_color_); + sh->set_light_position(light_pos_); + } + +public: + + QColor color_; + QColor ambiant_color_; + QVector3D light_pos_; + + ShaderParamPointSprite(ShaderPointSpriteTpl* sh) : + ShaderParam(sh), + color_(0, 0, 255), + ambiant_color_(5, 5, 5), + light_pos_(10, 100, 1000) + {} + + void set_all_vbos(VBO* vbo_pos, VBO* vbo_size) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + // position vbo + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderPointSpriteGen::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderPointSpriteGen::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + // size vbo + vbo_size->bind(); + ogl->glEnableVertexAttribArray(ShaderPointSpriteGen::ATTRIB_SIZE); + ogl->glVertexAttribPointer(ShaderPointSpriteGen::ATTRIB_SIZE, vbo_size->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_size->release(); + vao_->release(); + shader_->release(); + } + + void set_position_vbo(VBO* vbo_pos) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderPointSpriteGen::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderPointSpriteGen::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + vao_->release(); + shader_->release(); + } + + void set_size_vbo(VBO* vbo_size) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_size->bind(); + ogl->glEnableVertexAttribArray(ShaderPointSpriteGen::ATTRIB_SIZE); + ogl->glVertexAttribPointer(ShaderPointSpriteGen::ATTRIB_SIZE, vbo_size->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_size->release(); + vao_->release(); + shader_->release(); + } +}; + +template <> +class ShaderParamPointSprite : public ShaderParam +{ +protected: + + void set_uniforms() override + { + ShaderPointSpriteGen* sh = static_cast(this->shader_); + sh->set_ambiant(ambiant_color_); + sh->set_light_position(light_pos_); + sh->set_size(size_); + } + +public: + + QColor ambiant_color_; + QVector3D light_pos_; + float32 size_; + + ShaderParamPointSprite(ShaderPointSpriteTpl* sh) : + ShaderParam(sh), + ambiant_color_(5, 5, 5), + light_pos_(10, 100, 1000), + size_(1.0) + {} + + void set_all_vbos(VBO* vbo_pos, VBO* vbo_color) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + // position vbo + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderPointSpriteGen::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderPointSpriteGen::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + // color vbo + vbo_color->bind(); + ogl->glEnableVertexAttribArray(ShaderPointSpriteGen::ATTRIB_COLOR); + ogl->glVertexAttribPointer(ShaderPointSpriteGen::ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_color->release(); + vao_->release(); + shader_->release(); + } + + void set_position_vbo(VBO* vbo_pos) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderPointSpriteGen::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderPointSpriteGen::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + vao_->release(); + shader_->release(); + } + + void set_color_vbo(VBO* vbo_color) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_color->bind(); + ogl->glEnableVertexAttribArray(ShaderPointSpriteGen::ATTRIB_COLOR); + ogl->glVertexAttribPointer(ShaderPointSpriteGen::ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_color->release(); + vao_->release(); + shader_->release(); + } }; +template <> +class ShaderParamPointSprite : public ShaderParam +{ +protected: + + void set_uniforms() override + { + ShaderPointSpriteGen* sh = static_cast(this->shader_); + sh->set_ambiant(ambiant_color_); + sh->set_light_position(light_pos_); + } + +public: + + QColor ambiant_color_; + QVector3D light_pos_; + + ShaderParamPointSprite(ShaderPointSpriteTpl* sh) : + ShaderParam(sh), + ambiant_color_(5, 5, 5), + light_pos_(10, 100, 1000) + {} + + void set_all_vbos(VBO* vbo_pos, VBO* vbo_color, VBO* vbo_size) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + // position vbo + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderPointSpriteGen::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderPointSpriteGen::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + // color vbo + vbo_color->bind(); + ogl->glEnableVertexAttribArray(ShaderPointSpriteGen::ATTRIB_COLOR); + ogl->glVertexAttribPointer(ShaderPointSpriteGen::ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_color->release(); + // size vbo + vbo_size->bind(); + ogl->glEnableVertexAttribArray(ShaderPointSpriteGen::ATTRIB_SIZE); + ogl->glVertexAttribPointer(ShaderPointSpriteGen::ATTRIB_SIZE, vbo_size->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_size->release(); + vao_->release(); + shader_->release(); + } + + void set_position_vbo(VBO* vbo_pos) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderPointSpriteGen::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderPointSpriteGen::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + vao_->release(); + shader_->release(); + } + + void set_color_vbo(VBO* vbo_color) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_color->bind(); + ogl->glEnableVertexAttribArray(ShaderPointSpriteGen::ATTRIB_COLOR); + ogl->glVertexAttribPointer(ShaderPointSpriteGen::ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_color->release(); + vao_->release(); + shader_->release(); + } + + void set_size_vbo(VBO* vbo_size) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_size->bind(); + ogl->glEnableVertexAttribArray(ShaderPointSpriteGen::ATTRIB_SIZE); + ogl->glVertexAttribPointer(ShaderPointSpriteGen::ATTRIB_SIZE, vbo_size->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_size->release(); + vao_->release(); + shader_->release(); + } +}; + + +template +std::unique_ptr::Param> ShaderPointSpriteTpl::generate_param() +{ + if (!instance_) + instance_ = std::unique_ptr>(new ShaderPointSpriteTpl); + return cgogn::make_unique(instance_.get()); +} + + +using ShaderPointSprite = ShaderPointSpriteTpl; +using ShaderPointSpriteColor = ShaderPointSpriteTpl; +using ShaderPointSpriteSize = ShaderPointSpriteTpl; +using ShaderPointSpriteColorSize = ShaderPointSpriteTpl; + + +#if !defined(CGOGN_RENDER_SHADERS_POINT_SPRITE_CPP_) +extern template class CGOGN_RENDERING_API ShaderPointSpriteTpl; +extern template class CGOGN_RENDERING_API ShaderPointSpriteTpl; +extern template class CGOGN_RENDERING_API ShaderPointSpriteTpl; +extern template class CGOGN_RENDERING_API ShaderPointSpriteTpl; +extern template class CGOGN_RENDERING_API ShaderParamPointSprite; +extern template class CGOGN_RENDERING_API ShaderParamPointSprite; +extern template class CGOGN_RENDERING_API ShaderParamPointSprite; +extern template class CGOGN_RENDERING_API ShaderParamPointSprite; +#endif + } // namespace rendering } // namespace cgogn -#endif // RENDERING_SHADER_POINT_SPRITE_H_ +#endif // CGOGN_RENDERING_SHADER_POINT_SPRITE_H_ diff --git a/cgogn/rendering/shaders/shader_program.cpp b/cgogn/rendering/shaders/shader_program.cpp index 187b6aa2..8536b7d5 100644 --- a/cgogn/rendering/shaders/shader_program.cpp +++ b/cgogn/rendering/shaders/shader_program.cpp @@ -23,7 +23,8 @@ #define CGOGN_RENDERING_DLL_EXPORT -#include +#include +#include namespace cgogn { @@ -31,15 +32,45 @@ namespace cgogn namespace rendering { -ShaderProgram::~ShaderProgram() +ShaderParam::ShaderParam(ShaderProgram* prg): + shader_(prg) { - for (QOpenGLVertexArrayObject* vao : vaos_) - { - vao->destroy(); - delete vao; - } + vao_ = cgogn::make_unique(); + vao_->create(); +} + +ShaderParam::~ShaderParam() +{} + +void ShaderParam::bind_vao_only(bool with_uniforms) +{ + if (with_uniforms) + set_uniforms(); + vao_->bind(); +} + +void ShaderParam::release_vao_only() +{ + vao_->release(); } +void ShaderParam::bind(const QMatrix4x4& proj, const QMatrix4x4& mv) +{ + shader_->bind(); + shader_->set_matrices(proj,mv); + set_uniforms(); + vao_->bind(); +} + +void ShaderParam::release() +{ + vao_->release(); + shader_->release(); +} + +ShaderProgram::~ShaderProgram() +{} + void ShaderProgram::get_matrices_uniforms() { unif_mv_matrix_ = prg_.uniformLocation("model_view_matrix"); @@ -54,8 +85,8 @@ void ShaderProgram::set_matrices(const QMatrix4x4& proj, const QMatrix4x4& mv) if (unif_normal_matrix_ >= 0) { - QMatrix3x3 normalMatrix = mv.normalMatrix(); - prg_.setUniformValue(unif_normal_matrix_, normalMatrix); + QMatrix3x3 normal_matrix = mv.normalMatrix(); + prg_.setUniformValue(unif_normal_matrix_, normal_matrix); } } @@ -65,8 +96,8 @@ void ShaderProgram::set_view_matrix(const QMatrix4x4& mv) if (unif_normal_matrix_ >= 0) { - QMatrix3x3 normalMatrix = mv.normalMatrix(); - prg_.setUniformValue(unif_normal_matrix_, normalMatrix); + QMatrix3x3 normal_matrix = mv.normalMatrix(); + prg_.setUniformValue(unif_normal_matrix_, normal_matrix); } } diff --git a/cgogn/rendering/shaders/shader_program.h b/cgogn/rendering/shaders/shader_program.h index 590d58df..23746aaf 100644 --- a/cgogn/rendering/shaders/shader_program.h +++ b/cgogn/rendering/shaders/shader_program.h @@ -21,29 +21,79 @@ * * *******************************************************************************/ -#ifndef RENDERING_SHADERS_SHADERPROGRAM_H_ -#define RENDERING_SHADERS_SHADERPROGRAM_H_ +#ifndef CGOGN_RENDERING_SHADERS_SHADERPROGRAM_H_ +#define CGOGN_RENDERING_SHADERS_SHADERPROGRAM_H_ + +#include +#include #include #include #include -#include -#include - -#include +#include +#include +#include namespace cgogn { + namespace rendering { -//convenient conversion function +// convenient conversion function inline void* void_ptr(uint32 x) { return reinterpret_cast(uint64_t(x)); } +// forward +class ShaderProgram; + +class CGOGN_RENDERING_API ShaderParam +{ +protected: + + ShaderProgram* shader_; + std::unique_ptr vao_; + QOpenGLFunctions_3_3_Core* ogl33_; + + virtual void set_uniforms() = 0; + +public: + + ShaderParam(ShaderProgram* prg); + + virtual ~ShaderParam(); + + inline ShaderProgram* get_shader() + { + return shader_; + } + + /** + * @brief bind vao (and set uniform) + * @param with_uniforms ask to set uniforms + */ + void bind_vao_only(bool with_uniforms = true); + + /** + * @brief release vao + */ + void release_vao_only(); + + /** + * @brief bind the shader set uniforms & matrices, bind vao + * @param proj projectiob matrix + * @param mv model-view matrix + */ + void bind(const QMatrix4x4& proj, const QMatrix4x4& mv); + + /** + * @brief release vao adn shader + */ + void release(); +}; class CGOGN_RENDERING_API ShaderProgram : protected QOpenGLFunctions_3_3_Core { @@ -51,8 +101,6 @@ class CGOGN_RENDERING_API ShaderProgram : protected QOpenGLFunctions_3_3_Core QOpenGLShaderProgram prg_; - std::vector vaos_; - GLint unif_mv_matrix_; GLint unif_projection_matrix_; GLint unif_normal_matrix_; @@ -79,77 +127,19 @@ class CGOGN_RENDERING_API ShaderProgram : protected QOpenGLFunctions_3_3_Core */ void set_view_matrix(const QMatrix4x4& mv); - /** - * @brief add a vao (vbo configuration) - * @return the id of vao - */ - inline uint32 add_vao() - { - vaos_.push_back(new QOpenGLVertexArrayObject); - vaos_.back()->create(); - return uint32(vaos_.size() - 1); - } - - /** - * @brief allocate new vaos until total nb is reached - * @param nb number of vaos to reach - */ - void alloc_vao(uint32 nb) - { - while (vaos_.size() < nb) - vaos_.push_back(new QOpenGLVertexArrayObject); - } - - /** - * @brief number of allocated vaos - * @return the number of allocated vaos - */ - inline uint32 nb_vaos() - { - return (uint32)(vaos_.size()); - } - - /** - * @brief bind a vao - * @param i vao id (0,1,...) - */ - inline void bind_vao(uint32 i) - { -// assert(i < vaos_.size()); -// if (!vaos_[i]->isCreated()) -// vaos_[i]->create(); - vaos_[i]->bind(); - } - - /** - * @brief release the vao - * @param i id - */ - inline void release_vao(uint32 i) - { -// assert(i < vaos_.size()); - vaos_[i]->release(); - } - /** * @brief bind the shader */ - inline void bind() - { - prg_.bind(); - } + inline void bind() { prg_.bind(); } /** * @brief release the shader */ - inline void release() - { - prg_.release(); - } + inline void release() { prg_.release(); } }; } // namespace rendering } // namespace cgogn -#endif // RENDERING_SHADERS_SHADERPROGRAM_H_ +#endif // CGOGN_RENDERING_SHADERS_SHADERPROGRAM_H_ diff --git a/cgogn/rendering/shaders/shader_round_point.cpp b/cgogn/rendering/shaders/shader_round_point.cpp index e0e9b51f..04c8b69f 100644 --- a/cgogn/rendering/shaders/shader_round_point.cpp +++ b/cgogn/rendering/shaders/shader_round_point.cpp @@ -22,28 +22,27 @@ *******************************************************************************/ #define CGOGN_RENDERING_DLL_EXPORT +#define CGOGN_RENDER_SHADERS_ROUND_POINT_CPP_ -#include - -#include -#include #include +#include + + namespace cgogn { namespace rendering { -const char* ShaderRoundPoint::vertex_shader_source_ = +const char* ShaderRoundPointGen::vertex_shader_source_ = "#version 150\n" "in vec3 vertex_pos;\n" "void main() {\n" " gl_Position = vec4(vertex_pos,1.0);\n" "}\n"; - -const char* ShaderRoundPoint::geometry_shader_source_ = +const char* ShaderRoundPointGen::geometry_shader_source_ = "#version 150\n" "layout (points) in;\n" "layout (triangle_strip, max_vertices=4) out;\n" @@ -70,8 +69,7 @@ const char* ShaderRoundPoint::geometry_shader_source_ = " EndPrimitive();\n" "}\n"; - -const char* ShaderRoundPoint::fragment_shader_source_ = +const char* ShaderRoundPointGen::fragment_shader_source_ = "#version 150\n" "uniform vec4 color;\n" "in vec2 local;\n" @@ -83,10 +81,7 @@ const char* ShaderRoundPoint::fragment_shader_source_ = " fragColor = vec4(color.rgb,(1.0-r2*r2));\n" "}\n"; - - - -const char* ShaderRoundPoint::vertex_shader_source2_ = +const char* ShaderRoundPointGen::vertex_shader_source2_ = "#version 150\n" "in vec3 vertex_pos;\n" "in vec3 vertex_color;\n" @@ -96,8 +91,7 @@ const char* ShaderRoundPoint::vertex_shader_source2_ = " gl_Position = vec4(vertex_pos,1.0);\n" "}\n"; - -const char* ShaderRoundPoint::geometry_shader_source2_ = +const char* ShaderRoundPointGen::geometry_shader_source2_ = "#version 150\n" "layout (points) in;\n" "layout (triangle_strip, max_vertices=4) out;\n" @@ -127,7 +121,7 @@ const char* ShaderRoundPoint::geometry_shader_source2_ = " EndPrimitive();\n" "}\n"; -const char* ShaderRoundPoint::fragment_shader_source2_ = +const char* ShaderRoundPointGen::fragment_shader_source2_ = "#version 150\n" "in vec2 local;\n" "in vec3 color_f;\n" @@ -139,7 +133,8 @@ const char* ShaderRoundPoint::fragment_shader_source2_ = "}\n"; -ShaderRoundPoint::ShaderRoundPoint(bool color_per_vertex) + +ShaderRoundPointGen::ShaderRoundPointGen(bool color_per_vertex) { if (color_per_vertex) { @@ -161,62 +156,34 @@ ShaderRoundPoint::ShaderRoundPoint(bool color_per_vertex) get_matrices_uniforms(); unif_color_ = prg_.uniformLocation("color"); - unif_width_ = prg_.uniformLocation("pointSizes"); + unif_size_ = prg_.uniformLocation("pointSizes"); - set_width(3.0f); - set_color(QColor(255,255,255)); + set_size(3.0f); + set_color(QColor(255, 255, 255)); } - - -void ShaderRoundPoint::set_color(const QColor& rgb) +void ShaderRoundPointGen::set_color(const QColor& rgb) { - if (unif_color_>=0) + if (unif_color_ >= 0) prg_.setUniformValue(unif_color_, rgb); } -void ShaderRoundPoint::set_width(float32 wpix) +void ShaderRoundPointGen::set_size(float32 wpix) { - QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); int viewport[4]; ogl->glGetIntegerv(GL_VIEWPORT, viewport); QSizeF wd(wpix / float32(viewport[2]), wpix / float32(viewport[3])); - prg_.setUniformValue(unif_width_, wd); + prg_.setUniformValue(unif_size_, wd); } -bool ShaderRoundPoint::set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_color, uint32 stride, unsigned first) -{ - if (i >= vaos_.size()) - { - cgogn_log_warning("set_vao") << "VAO number " << i << " does not exist."; - return false; - } - - QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); - prg_.bind(); - vaos_[i]->bind(); - // position vbo - vbo_pos->bind(); - ogl->glEnableVertexAttribArray(ATTRIB_POS); - ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, stride*vbo_pos->vector_dimension()*4, void_ptr(first*vbo_pos->vector_dimension()*4)); - vbo_pos->release(); +template class CGOGN_RENDERING_API ShaderRoundPointTpl; +template class CGOGN_RENDERING_API ShaderRoundPointTpl; +template class CGOGN_RENDERING_API ShaderParamRoundPoint; +template class CGOGN_RENDERING_API ShaderParamRoundPoint; - if (vbo_color) - { - // color vbo - vbo_color->bind(); - ogl->glEnableVertexAttribArray(ATTRIB_COLOR); - ogl->glVertexAttribPointer(ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, stride*vbo_pos->vector_dimension()*4, void_ptr(first*vbo_pos->vector_dimension()*4)); - vbo_color->release(); - } - - vaos_[i]->release(); - prg_.release(); - - return true; -} } // namespace rendering diff --git a/cgogn/rendering/shaders/shader_round_point.h b/cgogn/rendering/shaders/shader_round_point.h index 73ed5f46..03aca975 100644 --- a/cgogn/rendering/shaders/shader_round_point.h +++ b/cgogn/rendering/shaders/shader_round_point.h @@ -21,12 +21,15 @@ * * *******************************************************************************/ -#ifndef RENDERING_SHADERS_ROUND_POINT_H_ -#define RENDERING_SHADERS_ROUND_POINT_H_ +#ifndef CGOGN_RENDERING_SHADERS_ROUND_POINT_H_ +#define CGOGN_RENDERING_SHADERS_ROUND_POINT_H_ -#include -#include -#include +#include +#include +#include + +#include +#include namespace cgogn { @@ -34,8 +37,17 @@ namespace cgogn namespace rendering { -class CGOGN_RENDERING_API ShaderRoundPoint : public ShaderProgram +// forward +template +class ShaderParamRoundPoint: public ShaderParam +{}; + +class CGOGN_RENDERING_API ShaderRoundPointGen : public ShaderProgram { + template friend class ShaderParamRoundPoint; + +protected: + static const char* vertex_shader_source_; static const char* geometry_shader_source_; static const char* fragment_shader_source_; @@ -44,19 +56,20 @@ class CGOGN_RENDERING_API ShaderRoundPoint : public ShaderProgram static const char* geometry_shader_source2_; static const char* fragment_shader_source2_; - enum - { - ATTRIB_POS = 0, - ATTRIB_COLOR - }; - // uniform ids GLint unif_color_; - GLint unif_width_; + GLint unif_size_; public: - ShaderRoundPoint(bool color_per_vertex = false); + using Self = ShaderRoundPointGen; + CGOGN_NOT_COPYABLE_NOR_MOVABLE(ShaderRoundPointGen); + + enum + { + ATTRIB_POS = 0, + ATTRIB_COLOR + }; /** * @brief set current color @@ -68,20 +81,160 @@ class CGOGN_RENDERING_API ShaderRoundPoint : public ShaderProgram * @brief set the width of lines (call before each draw) * @param w width in pixel */ - void set_width(float32 w); + void set_size(float32 w); - /** - * @brief set a vao configuration - * @param i vao id (0,1,...) - * @param vbo_pos pointer on position vbo (XYZ) - * @param vbo_color pointer on color vbo - * @return true if ok - */ - bool set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_color=NULL, uint32 stride=0, unsigned first=0); +protected: + + ShaderRoundPointGen(bool color_per_vertex); }; +template +class ShaderRoundPointTpl : public ShaderRoundPointGen +{ +public: + + using Param = ShaderParamRoundPoint; + static std::unique_ptr generate_param(); + +private: + + ShaderRoundPointTpl() : ShaderRoundPointGen(CPV) {} + static std::unique_ptr instance_; +}; + +template +std::unique_ptr> ShaderRoundPointTpl::instance_ = nullptr; + + +// COLOR UNIFORM PARAM +template <> +class ShaderParamRoundPoint : public ShaderParam +{ +protected: + + void set_uniforms() override + { + ShaderRoundPointGen* sh = static_cast(this->shader_); + sh->set_color(color_); + sh->set_size(size_); + } + +public: + + QColor color_; + float32 size_; + + ShaderParamRoundPoint(ShaderRoundPointTpl* sh): + ShaderParam(sh), + color_(0, 0, 255), + size_(1.0) + {} + + void set_position_vbo(VBO* vbo_pos, uint32 stride = 0, uint32 first = 0) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + // position vbo + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderRoundPointGen::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderRoundPointGen::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, stride * vbo_pos->vector_dimension() * 4, void_ptr(first * vbo_pos->vector_dimension() * 4)); + vbo_pos->release(); + vao_->release(); + shader_->release(); + } +}; + +// COLOR PER VERTEX PARAM +template <> +class ShaderParamRoundPoint : public ShaderParam +{ +protected: + + void set_uniforms() override + { + ShaderRoundPointGen* sh = static_cast(this->shader_); + sh->set_size(size_); + } + +public: + + float32 size_; + + ShaderParamRoundPoint(ShaderRoundPointTpl* sh): + ShaderParam(sh), + size_(1.0) + {} + + void set_all_vbos(VBO* vbo_pos, VBO* vbo_color, uint32 stride = 0, uint32 first = 0) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + // position vbo + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderRoundPointGen::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderRoundPointGen::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, stride * vbo_pos->vector_dimension() * 4, void_ptr(first * vbo_pos->vector_dimension() * 4)); + vbo_pos->release(); + // color vbo + vbo_color->bind(); + ogl->glEnableVertexAttribArray(ShaderRoundPointGen::ATTRIB_COLOR); + ogl->glVertexAttribPointer(ShaderRoundPointGen::ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, stride * vbo_color->vector_dimension() * 4, void_ptr(first * vbo_color->vector_dimension() * 4)); + vbo_color->release(); + vao_->release(); + shader_->release(); + } + + void set_position_vbo(VBO* vbo_pos, uint32 stride = 0, uint32 first = 0) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderRoundPointGen::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderRoundPointGen::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, stride * vbo_pos->vector_dimension() * 4, void_ptr(first * vbo_pos->vector_dimension() * 4)); + vbo_pos->release(); + vao_->release(); + shader_->release(); + } + + void set_color_vbo(VBO* vbo_color, uint32 stride = 0, uint32 first = 0) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_color->bind(); + ogl->glEnableVertexAttribArray(ShaderRoundPointGen::ATTRIB_COLOR); + ogl->glVertexAttribPointer(ShaderRoundPointGen::ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, stride * vbo_color->vector_dimension() * 4, void_ptr(first * vbo_color->vector_dimension() * 4)); + vbo_color->release(); + vao_->release(); + shader_->release(); + } +}; + + +template +std::unique_ptr::Param> ShaderRoundPointTpl::generate_param() +{ + if (!instance_) + instance_ = std::unique_ptr(new ShaderRoundPointTpl()); + return cgogn::make_unique(instance_.get()); +} + + +using ShaderRoundPoint = ShaderRoundPointTpl; +using ShaderRoundPointColor = ShaderRoundPointTpl; + + +#if !defined(CGOGN_RENDER_SHADERS_ROUND_POINT_CPP_) +extern template class CGOGN_RENDERING_API ShaderRoundPointTpl; +extern template class CGOGN_RENDERING_API ShaderRoundPointTpl; +extern template class CGOGN_RENDERING_API ShaderParamRoundPoint; +extern template class CGOGN_RENDERING_API ShaderParamRoundPoint; +#endif + } // namespace rendering } // namespace cgogn -#endif // RENDERING_SHADERS_ROUND_POINT_H_ +#endif // CGOGN_RENDERING_SHADERS_ROUND_POINT_H_ diff --git a/cgogn/rendering/shaders/shader_simple_color.cpp b/cgogn/rendering/shaders/shader_simple_color.cpp index 1374adb7..4809b418 100644 --- a/cgogn/rendering/shaders/shader_simple_color.cpp +++ b/cgogn/rendering/shaders/shader_simple_color.cpp @@ -23,11 +23,11 @@ #define CGOGN_RENDERING_DLL_EXPORT -#include +#include + +#include -#include #include -#include namespace cgogn { @@ -35,22 +35,31 @@ namespace cgogn namespace rendering { +std::unique_ptr ShaderSimpleColor::instance_ = nullptr; + +std::unique_ptr ShaderSimpleColor::generate_param() +{ + if (!instance_) + instance_ = std::unique_ptr(new ShaderSimpleColor()); + return cgogn::make_unique(instance_.get()); +} + const char* ShaderSimpleColor::vertex_shader_source_ = - "#version 150\n" - "in vec3 vertex_pos;\n" - "uniform mat4 projection_matrix;\n" - "uniform mat4 model_view_matrix;\n" - "void main() {\n" - " gl_Position = projection_matrix * model_view_matrix * vec4(vertex_pos,1.0);\n" - "}\n"; +"#version 150\n" +"in vec3 vertex_pos;\n" +"uniform mat4 projection_matrix;\n" +"uniform mat4 model_view_matrix;\n" +"void main() {\n" +" gl_Position = projection_matrix * model_view_matrix * vec4(vertex_pos,1.0);\n" +"}\n"; const char* ShaderSimpleColor::fragment_shader_source_ = - "#version 150\n" - "out vec4 fragColor;\n" - "uniform vec4 color;\n" - "void main() {\n" - " fragColor = color;\n" - "}\n"; +"#version 150\n" +"out vec4 fragColor;\n" +"uniform vec4 color;\n" +"void main() {\n" +" fragColor = color;\n" +"}\n"; ShaderSimpleColor::ShaderSimpleColor() { @@ -63,8 +72,8 @@ ShaderSimpleColor::ShaderSimpleColor() unif_color_ = prg_.uniformLocation("color"); - //default param - set_color(QColor(255,255,255)); + // default param + set_color(QColor(255, 255, 255)); } void ShaderSimpleColor::set_color(const QColor& rgb) @@ -72,34 +81,6 @@ void ShaderSimpleColor::set_color(const QColor& rgb) prg_.setUniformValue(unif_color_, rgb); } - -bool ShaderSimpleColor::set_vao(uint32 i, VBO* vbo_pos, uint32 stride, unsigned first) -{ - if (i >= vaos_.size()) - { - cgogn_log_warning("set_vao") << "VAO number " << i << " does not exist."; - return false; - } - - QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); - - prg_.bind(); - vaos_[i]->bind(); - - // position vbo - vbo_pos->bind(); - ogl->glEnableVertexAttribArray(ATTRIB_POS); - - ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, stride*vbo_pos->vector_dimension() * 4, - void_ptr(first*vbo_pos->vector_dimension() * 4)); - vbo_pos->release(); - - vaos_[i]->release(); - prg_.release(); - - return true; -} - } // namespace rendering } // namespace cgogn diff --git a/cgogn/rendering/shaders/shader_simple_color.h b/cgogn/rendering/shaders/shader_simple_color.h index f62874b1..46bbab1b 100644 --- a/cgogn/rendering/shaders/shader_simple_color.h +++ b/cgogn/rendering/shaders/shader_simple_color.h @@ -21,36 +21,45 @@ * * *******************************************************************************/ -#ifndef RENDERING_SHADERS_SIMPLECOLOR_H_ -#define RENDERING_SHADERS_SIMPLECOLOR_H_ +#ifndef CGOGN_RENDERING_SHADERS_SIMPLECOLOR_H_ +#define CGOGN_RENDERING_SHADERS_SIMPLECOLOR_H_ -#include -#include -#include +#include +#include +#include -class QColor; +#include +#include namespace cgogn { + namespace rendering { +class ShaderParamSimpleColor; + class CGOGN_RENDERING_API ShaderSimpleColor : public ShaderProgram { + friend class ShaderParamSimpleColor; + +protected: + static const char* vertex_shader_source_; static const char* fragment_shader_source_; - enum - { - ATTRIB_POS = 0 - }; - // uniform ids GLint unif_color_; public: - ShaderSimpleColor(); + enum + { + ATTRIB_POS = 0 + }; + + using Param = ShaderParamSimpleColor; + static std::unique_ptr generate_param(); /** * @brief set current color @@ -58,17 +67,47 @@ class CGOGN_RENDERING_API ShaderSimpleColor : public ShaderProgram */ void set_color(const QColor& rgb); - /** - * @brief set a vao configuration - * @param i id of vao (0,1,....) - * @param vbo_pos pointer on position vbo (XYZ) - * @return true if ok - */ - bool set_vao(uint32 i, VBO* vbo_pos, uint32 stride=0, unsigned first=0); +protected: + + ShaderSimpleColor(); + static std::unique_ptr instance_; +}; + +class CGOGN_RENDERING_API ShaderParamSimpleColor : public ShaderParam +{ +protected: + + inline void set_uniforms() override + { + ShaderSimpleColor* sh = static_cast(this->shader_); + sh->set_color(color_); + } + +public: + + QColor color_; + + ShaderParamSimpleColor(ShaderSimpleColor* sh) : + ShaderParam(sh), + color_(255, 255, 255) + {} + + inline void set_position_vbo(VBO* vbo_pos, uint32 stride = 0, uint32 first = 0) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderSimpleColor::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderSimpleColor::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, stride * vbo_pos->vector_dimension() * 4, void_ptr(first * vbo_pos->vector_dimension() * 4)); + vbo_pos->release(); + vao_->release(); + shader_->release(); + } }; } // namespace rendering } // namespace cgogn -#endif // RENDERING_SHADERS_SIMPLECOLOR_H_ +#endif // CGOGN_RENDERING_SHADERS_SIMPLECOLOR_H_ diff --git a/cgogn/rendering/shaders/shader_texture.cpp b/cgogn/rendering/shaders/shader_texture.cpp new file mode 100644 index 00000000..a67bd0d3 --- /dev/null +++ b/cgogn/rendering/shaders/shader_texture.cpp @@ -0,0 +1,112 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#define CGOGN_RENDERING_DLL_EXPORT + +#include +#include +#include + +namespace cgogn +{ + +namespace rendering +{ + +std::unique_ptr ShaderTexture::instance_ = nullptr; + +const char* ShaderTexture::vertex_shader_source_ = + "#version 150\n" + "in vec3 vertex_pos;\n" + "in vec2 vertex_tc;\n" + "uniform mat4 projection_matrix;\n" + "uniform mat4 model_view_matrix;\n" + "out vec2 tc;\n" + "void main() {\n" + " tc = vertex_tc;\n" + " gl_Position = projection_matrix * model_view_matrix * vec4(vertex_pos,1.0);\n" + "}\n"; + +const char* ShaderTexture::fragment_shader_source_ = + "#version 150\n" + "out vec4 frag_color;\n" + "uniform sampler2D texture_unit;\n" + "in vec2 tc;\n" + "void main() {\n" + " frag_color = texture(texture_unit,tc);\n" + "}\n"; + +ShaderTexture::ShaderTexture() +{ + prg_.addShaderFromSourceCode(QOpenGLShader::Vertex, vertex_shader_source_); + prg_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader_source_); + prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); + prg_.bindAttributeLocation("vertex_tc", ATTRIB_TC); + prg_.link(); + get_matrices_uniforms(); + prg_.setUniformValue("texture_unit", 0); +} + + +ShaderParamTexture::ShaderParamTexture(ShaderTexture* sh): + ShaderParam(sh), + texture_(nullptr) +{} + +void ShaderParamTexture::set_uniforms() +{ + if (texture_) + { + QOpenGLContext::currentContext()->functions()->glActiveTexture(GL_TEXTURE0); + texture_->bind(); + } +} + +void ShaderParamTexture::set_vbo(VBO* vbo_pos, VBO* vbo_tc) +{ + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + + shader_->bind(); + vao_->bind(); + + // position vbo + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderTexture::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderTexture::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + + // color vbo + vbo_tc->bind(); + ogl->glEnableVertexAttribArray(ShaderTexture::ATTRIB_TC); + ogl->glVertexAttribPointer(ShaderTexture::ATTRIB_TC, vbo_tc->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_tc->release(); + + vao_->release(); + shader_->release(); +} + + + +} // namespace rendering + +} // namespace cgogn diff --git a/cgogn/rendering/shaders/shader_texture.h b/cgogn/rendering/shaders/shader_texture.h new file mode 100644 index 00000000..35d81e6e --- /dev/null +++ b/cgogn/rendering/shaders/shader_texture.h @@ -0,0 +1,93 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef CGOGN_RENDERING_SHADERS_TEXTURE_H_ +#define CGOGN_RENDERING_SHADERS_TEXTURE_H_ + +#include +#include +#include +#include + +class QOpenGLTexture; + +namespace cgogn +{ + +namespace rendering +{ + +class ShaderTexture; + +class CGOGN_RENDERING_API ShaderParamTexture : public ShaderParam +{ +protected: + + void set_uniforms(); + +public: + + QOpenGLTexture* texture_; + + ShaderParamTexture(ShaderTexture* sh); + + void set_vbo(VBO* vbo_pos, VBO* vbo_tc); +}; + +class CGOGN_RENDERING_API ShaderTexture : public ShaderProgram +{ + static const char* vertex_shader_source_; + static const char* fragment_shader_source_; + +public: + + enum + { + ATTRIB_POS = 0, + ATTRIB_TC + }; + + using Param = ShaderParamTexture; + + /** + * @brief generate shader parameter object + * @return pointer + */ + inline static std::unique_ptr generate_param() + { + if (!instance_) + instance_ = std::unique_ptr(new ShaderTexture()); + return cgogn::make_unique(instance_.get()); + } + +protected: + + ShaderTexture(); + static std::unique_ptr instance_; +}; + +} // namespace rendering + +} // namespace cgogn + +#endif // CGOGN_RENDERING_SHADERS_TEXTURE_H_ diff --git a/cgogn/rendering/shaders/shader_vector_per_vertex.cpp b/cgogn/rendering/shaders/shader_vector_per_vertex.cpp index 28f86129..b6fdcaf6 100644 --- a/cgogn/rendering/shaders/shader_vector_per_vertex.cpp +++ b/cgogn/rendering/shaders/shader_vector_per_vertex.cpp @@ -23,11 +23,11 @@ #define CGOGN_RENDERING_DLL_EXPORT -#include +#include + +#include -#include #include -#include namespace cgogn { @@ -35,40 +35,51 @@ namespace cgogn namespace rendering { +std::unique_ptr ShaderVectorPerVertex::instance_ = nullptr; + +std::unique_ptr ShaderVectorPerVertex::generate_param() +{ + if (!instance_) + instance_ = std::unique_ptr(new ShaderVectorPerVertex()); + return cgogn::make_unique(instance_.get()); +} + const char* ShaderVectorPerVertex::vertex_shader_source_ = - "#version 150\n" - "in vec3 vertex_pos;\n" - "in vec3 vertex_normal;\n" - "out vec3 normal;\n" - "void main() {\n" - " normal = vertex_normal;\n" - " gl_Position = vec4(vertex_pos,1.0);\n" - "}\n"; +"#version 150\n" +"in vec3 vertex_pos;\n" +"in vec3 vertex_normal;\n" +"out vec3 normal;\n" +"void main() {\n" +" normal = vertex_normal;\n" +" gl_Position = vec4(vertex_pos,1.0);\n" +"}\n"; const char* ShaderVectorPerVertex::geometry_shader_source_ = - "#version 150\n" - "layout(points) in;\n" - "layout(line_strip,max_vertices=2) out;\n" - "in vec3 normal[];\n" - "uniform mat4 projection_matrix;\n" - "uniform mat4 model_view_matrix;\n" - "uniform float length;\n" - "void main() {\n" - " gl_Position = projection_matrix * model_view_matrix * gl_in[0].gl_Position;\n" - " EmitVertex();\n" - " vec4 end_point = gl_in[0].gl_Position + vec4(length * normal[0], 0.0);\n" - " gl_Position = projection_matrix * model_view_matrix * end_point;\n" - " EmitVertex();\n" - " EndPrimitive();\n" - "}\n"; +"#version 150\n" +"layout(points) in;\n" +"layout(line_strip,max_vertices=2) out;\n" +"in vec3 normal[];\n" +"uniform mat4 projection_matrix;\n" +"uniform mat4 model_view_matrix;\n" +"uniform float length;\n" +"void main() {\n" +" gl_Position = projection_matrix * model_view_matrix * gl_in[0].gl_Position;\n" +" EmitVertex();\n" +" vec4 end_point = gl_in[0].gl_Position + vec4(length * normal[0], 0.0);\n" +" gl_Position = projection_matrix * model_view_matrix * end_point;\n" +" EmitVertex();\n" +" EndPrimitive();\n" +"}\n"; const char* ShaderVectorPerVertex::fragment_shader_source_ = - "#version 150\n" - "uniform vec4 color;\n" - "out vec4 fragColor;\n" - "void main() {\n" - " fragColor = color;\n" - "}\n"; +"#version 150\n" +"uniform vec4 color;\n" +"out vec4 fragColor;\n" +"void main() {\n" +" fragColor = color;\n" +"}\n"; + + ShaderVectorPerVertex::ShaderVectorPerVertex() { @@ -85,7 +96,7 @@ ShaderVectorPerVertex::ShaderVectorPerVertex() unif_length_ = prg_.uniformLocation("length"); //default param - set_color(QColor(255,255,255)); + set_color(QColor(255, 255, 255)); set_length(1.0); } @@ -99,37 +110,6 @@ void ShaderVectorPerVertex::set_length(float32 l) prg_.setUniformValue(unif_length_, l); } -bool ShaderVectorPerVertex::set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_normal) -{ - if (i >= vaos_.size()) - { - cgogn_log_warning("set_vao") << "VAO number " << i << " does not exist."; - return false; - } - - QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); - - prg_.bind(); - vaos_[i]->bind(); - - // position vbo - vbo_pos->bind(); - ogl->glEnableVertexAttribArray(ATTRIB_POS); - ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); - vbo_pos->release(); - - // normal vbo - vbo_normal->bind(); - ogl->glEnableVertexAttribArray(ATTRIB_NORMAL); - ogl->glVertexAttribPointer(ATTRIB_NORMAL, vbo_normal->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); - vbo_normal->release(); - - vaos_[i]->release(); - prg_.release(); - - return true; -} - } // namespace rendering } // namespace cgogn diff --git a/cgogn/rendering/shaders/shader_vector_per_vertex.h b/cgogn/rendering/shaders/shader_vector_per_vertex.h index 13dc0fdf..01682448 100644 --- a/cgogn/rendering/shaders/shader_vector_per_vertex.h +++ b/cgogn/rendering/shaders/shader_vector_per_vertex.h @@ -21,12 +21,15 @@ * * *******************************************************************************/ -#ifndef RENDERING_SHADERS_VECTORPERVERTEX_H_ -#define RENDERING_SHADERS_VECTORPERVERTEX_H_ +#ifndef CGOGN_RENDERING_SHADERS_VECTORPERVERTEX_H_ +#define CGOGN_RENDERING_SHADERS_VECTORPERVERTEX_H_ -#include -#include -#include +#include +#include +#include + +#include +#include namespace cgogn { @@ -34,25 +37,30 @@ namespace cgogn namespace rendering { +class ShaderParamVectorPerVertex; + class CGOGN_RENDERING_API ShaderVectorPerVertex : public ShaderProgram { + friend class ShaderParamVectorPerVertex; + static const char* vertex_shader_source_; static const char* geometry_shader_source_; static const char* fragment_shader_source_; - enum - { - ATTRIB_POS = 0, - ATTRIB_NORMAL - }; - // uniform ids GLint unif_color_; GLint unif_length_; public: - ShaderVectorPerVertex(); + enum + { + ATTRIB_POS = 0, + ATTRIB_NORMAL + }; + + using Param = ShaderParamVectorPerVertex; + static std::unique_ptr generate_param(); /** * @brief set current color @@ -66,18 +74,82 @@ class CGOGN_RENDERING_API ShaderVectorPerVertex : public ShaderProgram */ void set_length(float32 l); - /** - * @brief set a vao configuration - * @param i vao id (0,1,...) - * @param vbo_pos pointer on position vbo (XYZ) - * @param vbo_norm pointer on normal vbo - * @return true if ok - */ - bool set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_norm); +protected: + + ShaderVectorPerVertex(); + static std::unique_ptr instance_; +}; + +class CGOGN_RENDERING_API ShaderParamVectorPerVertex : public ShaderParam +{ +protected: + + inline void set_uniforms() override + { + ShaderVectorPerVertex* sh = static_cast(this->shader_); + sh->set_color(color_); + sh->set_length(length_); + } + +public: + + QColor color_; + float32 length_; + + ShaderParamVectorPerVertex(ShaderVectorPerVertex* sh) : + ShaderParam(sh), + color_(255, 255, 255), + length_(1.0) + {} + + void set_all_vbos(VBO* vbo_pos, VBO* vbo_vect) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + // position vbo + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderVectorPerVertex::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderVectorPerVertex::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + // vector vbo + vbo_vect->bind(); + ogl->glEnableVertexAttribArray(ShaderVectorPerVertex::ATTRIB_NORMAL); + ogl->glVertexAttribPointer(ShaderVectorPerVertex::ATTRIB_NORMAL, vbo_vect->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_vect->release(); + vao_->release(); + shader_->release(); + } + + void set_position_vbo(VBO* vbo_pos) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ShaderVectorPerVertex::ATTRIB_POS); + ogl->glVertexAttribPointer(ShaderVectorPerVertex::ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + vao_->release(); + shader_->release(); + } + + void set_vector_vbo(VBO* vbo_vect) + { + QOpenGLFunctions* ogl = QOpenGLContext::currentContext()->functions(); + shader_->bind(); + vao_->bind(); + vbo_vect->bind(); + ogl->glEnableVertexAttribArray(ShaderVectorPerVertex::ATTRIB_NORMAL); + ogl->glVertexAttribPointer(ShaderVectorPerVertex::ATTRIB_NORMAL, vbo_vect->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_vect->release(); + vao_->release(); + shader_->release(); + } }; } // namespace rendering } // namespace cgogn -#endif // RENDERING_SHADERS_VECTORPERVERTEX_H_ +#endif // CGOGN_RENDERING_SHADERS_VECTORPERVERTEX_H_ diff --git a/cgogn/rendering/shaders/vbo.h b/cgogn/rendering/shaders/vbo.h index 78efbcf7..2f1714fd 100644 --- a/cgogn/rendering/shaders/vbo.h +++ b/cgogn/rendering/shaders/vbo.h @@ -22,13 +22,13 @@ * * *******************************************************************************/ -#ifndef RENDERING_SHADERS_VBO_H_ -#define RENDERING_SHADERS_VBO_H_ +#ifndef CGOGN_RENDERING_SHADERS_VBO_H_ +#define CGOGN_RENDERING_SHADERS_VBO_H_ #include -#include -#include +#include +#include namespace cgogn { @@ -43,14 +43,20 @@ class VBO uint32 nb_vectors_; uint32 vector_dimension_; QOpenGLBuffer buffer_; + std::string name_; public: - inline VBO(uint32 vec_dim) : + inline VBO(uint32 vec_dim = 3u) : nb_vectors_(), vector_dimension_(vec_dim) { - buffer_.create(); + const bool buffer_created = buffer_.create(); + if (!buffer_created) + { + cgogn_log_error("VBO::VBO(uint32)") << "The call to QOpenGLBuffer::create() failed. Maybe there is no QOpenGLContext."; + std::exit(EXIT_FAILURE); + } buffer_.bind(); buffer_.setUsagePattern(QOpenGLBuffer::StreamDraw); } @@ -60,6 +66,16 @@ class VBO buffer_.destroy(); } + inline void set_name(const std::string& name) + { + name_ = name; + } + + inline const std::string& get_name() const + { + return name_; + } + inline void bind() { buffer_.bind(); @@ -134,34 +150,37 @@ class VBO }; /** - * @brief update vbo from one AttributeHandler - * @param attr AttributeHandler (must contain float or vec + * @brief update vbo from one Attribute + * @param attr Attribute (must contain float or vec * @param vbo vbo to update * @param convert conversion lambda */ template -void update_vbo(const ATTR& attr, VBO& vbo) +void update_vbo(const ATTR& attr, VBO* vbo) { static_assert(std::is_same::Scalar, float32>::value || std::is_same::Scalar, double>::value, "only float or double allowed for vbo"); const typename ATTR::TChunkArray* ca = attr.get_data(); + // set vbo name based on attribute name + vbo->set_name(attr.get_name()); + std::vector chunk_addr; uint32 byte_chunk_size; uint32 nb_chunks = ca->get_chunks_pointers(chunk_addr, byte_chunk_size); const uint32 vec_dim = geometry::nb_components_traits::value; - vbo.allocate(nb_chunks * ATTR::CHUNKSIZE, vec_dim); + vbo->allocate(nb_chunks * ATTR::CHUNKSIZE, vec_dim); const uint32 vbo_blk_bytes = ATTR::CHUNKSIZE * vec_dim * sizeof(float32); if (std::is_same::Scalar, float32>::value) { // copy - vbo.bind(); + vbo->bind(); for (uint32 i = 0; i < nb_chunks; ++i) - vbo.copy_data(i* vbo_blk_bytes, vbo_blk_bytes, chunk_addr[i]); - vbo.release(); + vbo->copy_data(i* vbo_blk_bytes, vbo_blk_bytes, chunk_addr[i]); + vbo->release(); } else if (std::is_same::Scalar, float64>::value) { @@ -174,23 +193,22 @@ void update_vbo(const ATTR& attr, VBO& vbo) float64* src = reinterpret_cast(chunk_addr[i]); for (uint32 j = 0; j < ATTR::CHUNKSIZE * vec_dim; ++j) *fit++ = *src++; - vbo.bind(); - vbo.copy_data(i* ATTR::CHUNKSIZE * vec_dim * sizeof(float32), ATTR::CHUNKSIZE * vec_dim * sizeof(float32),float_buffer); - vbo.release(); + vbo->bind(); + vbo->copy_data(i* ATTR::CHUNKSIZE * vec_dim * sizeof(float32), ATTR::CHUNKSIZE * vec_dim * sizeof(float32),float_buffer); + vbo->release(); } delete[] float_buffer; } } - /** - * @brief update vbo from one AttributeHandler with conversion lambda - * @param attr AttributeHandler + * @brief update vbo from one Attribute with conversion lambda + * @param attr Attribute * @param vbo vbo to update * @param convert conversion lambda -> float or std::array */ template -void update_vbo(const ATTR& attr, VBO& vbo, const FUNC& convert) +void update_vbo(const ATTR& attr, VBO* vbo, const FUNC& convert) { // check that convert has 1 param static_assert(function_traits::arity == 1, "convert lambda function must have only one arg"); @@ -199,6 +217,9 @@ void update_vbo(const ATTR& attr, VBO& vbo, const FUNC& convert) using InputConvert = typename std::remove_cv< typename std::remove_reference::template arg<0>::type>::type >::type; static_assert(std::is_same::value, "wrong parameter 1"); + // set vbo name based on attribute name + vbo->set_name(attr.get_name()); + // get chunk data pointers const typename ATTR::TChunkArray* ca = attr.get_data(); std::vector chunk_addr; @@ -222,30 +243,30 @@ void update_vbo(const ATTR& attr, VBO& vbo, const FUNC& convert) else if (check_func_return_type(FUNC,Vec4f) ) vec_dim = 4; - vbo.allocate(nb_chunks * ATTR::CHUNKSIZE, vec_dim); + vbo->allocate(nb_chunks * ATTR::CHUNKSIZE, vec_dim); // copy (after conversion) using OutputConvert = typename function_traits::result_type; - OutputConvert* dst = reinterpret_cast(vbo.lock_pointer()); + OutputConvert* dst = reinterpret_cast(vbo->lock_pointer()); for (uint32 i = 0; i < nb_chunks; ++i) { InputConvert* typed_chunk = static_cast(chunk_addr[i]); for (uint32 j = 0; j < ATTR::CHUNKSIZE; ++j) *dst++ = convert(typed_chunk[j]); } - vbo.release_pointer(); -} + vbo->release_pointer(); +} /** - * @brief update vbo from two AttributeHandlers with conversion lambda - * @param attr first AttributeHandler - * @param attr2 second AttributeHandler + * @brief update vbo from two Attributes with conversion lambda + * @param attr first Attribute + * @param attr2 second Attribute * @param vbo vbo to update * @param convert conversion lambda -> float or std::array */ template -void update_vbo(const ATTR& attr, const ATTR2& attr2, VBO& vbo, const FUNC& convert) +void update_vbo(const ATTR& attr, const ATTR2& attr2, VBO* vbo, const FUNC& convert) { // check that convert has 2 param static_assert(function_traits::arity == 2, "convert lambda function must have two arg"); @@ -261,6 +282,9 @@ void update_vbo(const ATTR& attr, const ATTR2& attr2, VBO& vbo, const FUNC& conv using InputConvert2 = typename std::remove_cv< typename std::remove_reference::template arg<1>::type>::type >::type; static_assert(std::is_same::value, "wrong parameter 2"); + // set vbo name based on first attribute name + vbo->set_name(attr.get_name()); + // get chunk data pointers const typename ATTR::TChunkArray* ca = attr.get_data(); std::vector chunk_addr; @@ -289,12 +313,12 @@ void update_vbo(const ATTR& attr, const ATTR2& attr2, VBO& vbo, const FUNC& conv vec_dim = 4; // allocate vbo - vbo.allocate(nb_chunks * ATTR::CHUNKSIZE, vec_dim); + vbo->allocate(nb_chunks * ATTR::CHUNKSIZE, vec_dim); // copy (after conversion) // out type conversion using OutputConvert = typename function_traits::result_type; - OutputConvert* dst = reinterpret_cast(vbo.lock_pointer()); + OutputConvert* dst = reinterpret_cast(vbo->lock_pointer()); for (uint32 i = 0; i < nb_chunks; ++i) { InputConvert* typed_chunk = static_cast(chunk_addr[i]); @@ -302,20 +326,19 @@ void update_vbo(const ATTR& attr, const ATTR2& attr2, VBO& vbo, const FUNC& conv for (uint32 j = 0; j < ATTR::CHUNKSIZE; ++j) *dst++ = convert(typed_chunk[j],typed_chunk2[j]); } - vbo.release_pointer(); -} - + vbo->release_pointer(); +} /** * @brief generate a vbo from an attribute and it's indices - * @param attr the AttributeHandler - * @param indices indices in the AttributeHandler + * @param attr the Attribute + * @param indices indices in the Attribute * @param vbo the vbo to generate * @param convert conversion lambda -> float or std::array */ template -void generate_vbo(const ATTR& attr, const std::vector& indices, VBO& vbo, const FUNC& convert) +void generate_vbo(const ATTR& attr, const std::vector& indices, VBO* vbo, const FUNC& convert) { // check that convert has 1 param static_assert(function_traits::arity == 1, "convert lambda function must have only one arg"); @@ -341,26 +364,24 @@ void generate_vbo(const ATTR& attr, const std::vector& indices, VBO& vbo else if (check_func_return_type(FUNC,Vec4f) ) vec_dim = 4; + // set vbo name based on attribute name + vbo->set_name(attr.get_name()); + // allocate vbo - vbo.allocate(uint32(indices.size()), vec_dim); + vbo->allocate(uint32(indices.size()), vec_dim); // copy (after conversion) using OutputConvert = typename function_traits::result_type; - OutputConvert* dst = reinterpret_cast(vbo.lock_pointer()); + OutputConvert* dst = reinterpret_cast(vbo->lock_pointer()); for (uint32 i: indices) *dst++ = convert(attr[i]); - vbo.release_pointer(); + vbo->release_pointer(); } - - - - - } // namespace rendering } // namespace cgogn -#endif // RENDERING_SHADERS_VBO_H_ +#endif // CGOGN_RENDERING_SHADERS_VBO_H_ diff --git a/cgogn/rendering/topo_drawer.cpp b/cgogn/rendering/topo_drawer.cpp new file mode 100644 index 00000000..acd58017 --- /dev/null +++ b/cgogn/rendering/topo_drawer.cpp @@ -0,0 +1,114 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#define CGOGN_RENDERING_DLL_EXPORT + +#include + +#include +#include +#include + +namespace cgogn +{ + +namespace rendering +{ + +TopoDrawer::TopoDrawer(): + dart_color_(255, 255, 255), + phi2_color_(255, 0, 0), + phi3_color_(255, 255, 0), + shrink_v_(0.6f), + shrink_f_(0.85f), + shrink_e_(0.95f) +{ + vbo_darts_ = cgogn::make_unique(3); + vbo_relations_ = cgogn::make_unique(3); +} + +TopoDrawer::~TopoDrawer() +{ +} + +TopoDrawer::Renderer::Renderer(TopoDrawer* tr): + topo_drawer_data_(tr) +{ + param_bl_ = ShaderBoldLine::generate_param(); + param_bl_->set_position_vbo(tr->vbo_darts_.get()); + param_bl_->color_= tr->dart_color_; + + param_bl2_ = ShaderBoldLine::generate_param(); + param_bl2_->set_position_vbo(tr->vbo_relations_.get()); + param_bl2_->color_= tr->phi2_color_; + + param_rp_ = ShaderRoundPoint::generate_param(); + param_rp_->set_position_vbo(tr->vbo_darts_.get(), 2, 0); + param_rp_->color_ = tr->dart_color_; +} + +TopoDrawer::Renderer::~Renderer() +{} + +void TopoDrawer::Renderer::draw(const QMatrix4x4& projection, const QMatrix4x4& modelview, QOpenGLFunctions_3_3_Core* ogl33, bool with_blending) +{ + float32 lw = 2.0; + if(with_blending) + { + ogl33->glEnable(GL_BLEND); + ogl33->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + lw = 3.0; + } + + param_bl_->width_ = lw; + param_bl2_->width_ = lw; + param_rp_->size_ = 2*lw; + + param_rp_->bind(projection,modelview); + ogl33->glDrawArrays(GL_POINTS,0,topo_drawer_data_->vbo_darts_->size()/2); + param_rp_->release(); + + param_bl_->bind(projection,modelview); + ogl33->glDrawArrays(GL_LINES,0,topo_drawer_data_->vbo_darts_->size()); + param_bl_->release(); + + param_bl2_->color_ = topo_drawer_data_->phi2_color_; + param_bl2_->bind(projection,modelview); + ogl33->glDrawArrays(GL_LINES,0,topo_drawer_data_->vbo_darts_->size()); + param_bl2_->release(); + + if (topo_drawer_data_->vbo_relations_->size() > topo_drawer_data_->vbo_darts_->size()) + { + param_bl2_->color_ = topo_drawer_data_->phi3_color_; + param_bl2_->bind(projection,modelview); + ogl33->glDrawArrays(GL_LINES,topo_drawer_data_->vbo_darts_->size(),topo_drawer_data_->vbo_darts_->size()); + param_bl2_->release(); + } + ogl33->glDisable(GL_BLEND); + +} + + +} // namespace rendering + +} // namespace cgogn diff --git a/cgogn/rendering/topo_render.h b/cgogn/rendering/topo_drawer.h similarity index 52% rename from cgogn/rendering/topo_render.h rename to cgogn/rendering/topo_drawer.h index 343b07f9..456e8bc0 100644 --- a/cgogn/rendering/topo_render.h +++ b/cgogn/rendering/topo_drawer.h @@ -21,46 +21,51 @@ * * *******************************************************************************/ -#ifndef RENDERING_TOPO_RENDER_H_ -#define RENDERING_TOPO_RENDER_H_ - -#include -#include -#include -#include -#include +#ifndef CGOGN_RENDERING_TOPO_RENDER_H_ +#define CGOGN_RENDERING_TOPO_RENDER_H_ + +#include + +#include +#include +#include +#include + +#include + #include #include -#include - namespace cgogn { namespace rendering { - - -class CGOGN_RENDERING_API TopoRender +/** + * @brief Rendering of the topology + * + * Typical usage: + * + * std::unique_ptr topo_; // can be shared between contexts + * std::unique_ptr topo_rend_; // one by context, + * + * init: + * topo_ = cgogn::make_unique(); + * topo_rend_ = topo_->generate_renderer(); + * topo_->update(map_,vertex_position_); + * + * draw: + * topo_rend_->draw(proj,view,this); + * + */ +class CGOGN_RENDERING_API TopoDrawer { - using Vec3f = std::array; + using Vec3f = std::array; protected: - static ShaderSimpleColor* shader_cpv_; - static ShaderBoldLine* shader_bl_; - static ShaderRoundPoint* shader_rp_; - static int32 nb_instances_; - - VBO* vbo_darts_; - VBO* vbo_relations_; - - uint32 vao_bl_; - uint32 vao_bl2_; - uint32 vao_rp_; - - QOpenGLFunctions_3_3_Core* ogl33_; - + std::unique_ptr vbo_darts_; + std::unique_ptr vbo_relations_; QColor dart_color_; QColor phi2_color_; @@ -70,49 +75,92 @@ class CGOGN_RENDERING_API TopoRender float32 shrink_f_; float32 shrink_e_; + template + void update_map2(const MAP& m, const typename MAP::template VertexAttribute& position); + + template + void update_map3(const MAP& m, const typename MAP::template VertexAttribute& position); + public: - using Self = TopoRender; + + class CGOGN_RENDERING_API Renderer + { + friend class TopoDrawer; + std::unique_ptr param_bl_; + std::unique_ptr param_bl2_; + std::unique_ptr param_rp_; + TopoDrawer* topo_drawer_data_; + Renderer(TopoDrawer* tr); + public: + ~Renderer(); + /** + * @brief draw + * @param projection projection matrix + * @param modelview model-view matrix + * @param ogl33 OGLFunction (use "this" ptr if you inherit from QOpenGLWidget + * @param with_blending + */ + void draw(const QMatrix4x4& projection, const QMatrix4x4& modelview, QOpenGLFunctions_3_3_Core* ogl33, bool with_blending = true); + }; + + using Self = TopoDrawer; + /** * constructor, init all buffers (data and OpenGL) and shader * @Warning need OpenGL context */ - TopoRender(QOpenGLFunctions_3_3_Core* ogl33); - CGOGN_NOT_COPYABLE_NOR_MOVABLE(TopoRender); + TopoDrawer(); + + CGOGN_NOT_COPYABLE_NOR_MOVABLE(TopoDrawer); + /** * release buffers and shader */ - ~TopoRender(); + ~TopoDrawer(); + + /** + * @brief generate a renderer (one per context) + * @return pointer on renderer + */ + inline std::unique_ptr generate_renderer() + { + return std::unique_ptr(new Renderer(this)); + } inline void set_explode_volume(float32 x) { shrink_v_ = x; } - inline void set_explode_face(float32 x) { shrink_f_ = x; } - inline void set_explode_edge(float32 x) { shrink_e_ = x; } - template - void update_map2(MAP& m, const typename MAP::template VertexAttributeHandler& position); + inline void set_explode_face(float32 x) { shrink_f_ = x; } - template - void update_map3(MAP& m, const typename MAP::template VertexAttributeHandler& position); + inline void set_explode_edge(float32 x) { shrink_e_ = x; } + template ::type* = nullptr> + void update(const MAP& m, const typename MAP::template VertexAttribute& position) + { + this->update_map2(m, position); + } - void draw(const QMatrix4x4& projection, const QMatrix4x4& modelview, bool with_blending=true); + template ::type* = nullptr> + void update(const MAP& m, const typename MAP::template VertexAttribute& position) + { + this->update_map3(m, position); + } }; template -void TopoRender::update_map2(MAP& m, const typename MAP::template VertexAttributeHandler& position) +void TopoDrawer::update_map2(const MAP& m, const typename MAP::template VertexAttribute& position) { using Vertex = typename MAP::Vertex; using Face = typename MAP::Face; using Scalar = typename VEC3::Scalar; - Scalar opp_shrink_e = 1.0 -shrink_e_; + Scalar opp_shrink_e = 1.0 - shrink_e_; Scalar opp_shrink_f = 1.0 - shrink_f_; - std::vector> out_pos; - out_pos.reserve(1024*1024); - - std::vector> out_pos2; - out_pos2.reserve(1024*1024); + std::vector out_pos; + out_pos.reserve(1024 * 1024); + std::vector out_pos2; + out_pos2.reserve(1024 * 1024); std::vector local_vertices; local_vertices.reserve(256); @@ -132,78 +180,74 @@ void TopoRender::update_map2(MAP& m, const typename MAP::template VertexAttribut center /= Scalar(count); // phi2 mid-edge: N -> 2N-1 - for (uint32 i=0; i N-1 - for (uint32 i=0; i 3N-1 - for (uint32 i=0; i 4N-1 - for (uint32 i=0; iallocate(nbvec,3); + + vbo_darts_->allocate(nbvec, 3); vbo_darts_->bind(); - vbo_darts_->copy_data(0, nbvec*12, out_pos[0].data()); + vbo_darts_->copy_data(0, nbvec * 12, out_pos[0].data()); vbo_darts_->release(); - vbo_relations_->allocate(nbvec,3); + vbo_relations_->allocate(nbvec, 3); vbo_relations_->bind(); - vbo_relations_->copy_data(0, nbvec*12, out_pos2[0].data()); + vbo_relations_->copy_data(0, nbvec * 12, out_pos2[0].data()); vbo_relations_->release(); - - } - template -void TopoRender::update_map3(MAP& m, const typename MAP::template VertexAttributeHandler& position) +void TopoDrawer::update_map3(const MAP& m, const typename MAP::template VertexAttribute& position) { using Vertex = typename MAP::Vertex; using Face = typename MAP::Face; using Volume = typename MAP::Volume; using Scalar = typename VEC3::Scalar; - Scalar opp_shrink_e = 1.0 -shrink_e_; + Scalar opp_shrink_e = 1.0 - shrink_e_; Scalar opp_shrink_f = 1.0 - shrink_f_; Scalar opp_shrink_v = 1.0 - shrink_v_; - std::vector> out_pos; - out_pos.reserve(1024*1024); - - std::vector> out_pos2; - out_pos2.reserve(1024*1024); + std::vector out_pos; + out_pos.reserve(1024 * 1024); - std::vector> out_pos3; - out_pos3.reserve(1024*1024); + std::vector out_pos2; + out_pos2.reserve(1024 * 1024); + std::vector out_pos3; + out_pos3.reserve(1024 * 1024); std::vector local_vertices; local_vertices.reserve(256); m.foreach_cell([&] (Volume v) { - VEC3 center_vol = geometry::centroid(m,v,position); + VEC3 center_vol = geometry::centroid(m, v, position); m.foreach_incident_face(v, [&] (Face f) { local_vertices.clear(); @@ -219,63 +263,59 @@ void TopoRender::update_map3(MAP& m, const typename MAP::template VertexAttribut center /= Scalar(count); // phi2 mid-edge: N -> 2N-1 - for (uint32 i=0; i 3N-1 - for (uint32 i=0; i N-1 - for (uint32 i=0; i 4N-1 - for (uint32 i=0; i 5N-1 - for (uint32 i=0; iallocate(nbvec,3); + uint32 nbvec = uint32(out_pos.size()); + vbo_darts_->allocate(nbvec, 3); vbo_darts_->bind(); - vbo_darts_->copy_data(0, nbvec*12, out_pos[0].data()); + vbo_darts_->copy_data(0, nbvec * 12, out_pos[0].data()); vbo_darts_->release(); - vbo_relations_->allocate(2*nbvec,3); + vbo_relations_->allocate(2 * nbvec, 3); vbo_relations_->bind(); - vbo_relations_->copy_data(0, nbvec*12, out_pos2[0].data()); - vbo_relations_->copy_data(nbvec*12, nbvec*12, out_pos3[0].data()); + vbo_relations_->copy_data(0, nbvec * 12, out_pos2[0].data()); + vbo_relations_->copy_data(nbvec * 12, nbvec*12, out_pos3[0].data()); vbo_relations_->release(); - - } } // namespace rendering } // namespace cgogn -#endif // RENDERING_TOPO_RENDER_H_ +#endif // CGOGN_RENDERING_TOPO_RENDER_H_ diff --git a/cgogn/rendering/topo_render.cpp b/cgogn/rendering/topo_render.cpp deleted file mode 100644 index 4eb40fc7..00000000 --- a/cgogn/rendering/topo_render.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/******************************************************************************* -* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * -* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * -* * -* This library is free software; you can redistribute it and/or modify it * -* under the terms of the GNU Lesser General Public License as published by the * -* Free Software Foundation; either version 2.1 of the License, or (at your * -* option) any later version. * -* * -* This library is distributed in the hope that it will be useful, but WITHOUT * -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * -* for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with this library; if not, write to the Free Software Foundation, * -* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * -* * -* Web site: http://cgogn.unistra.fr/ * -* Contact information: cgogn@unistra.fr * -* * -*******************************************************************************/ - -#define CGOGN_RENDERING_DLL_EXPORT - -#include - -#include -#include -#include - -namespace cgogn -{ - -namespace rendering -{ - -// static members init -ShaderSimpleColor* TopoRender::shader_cpv_ = nullptr; -ShaderBoldLine* TopoRender::shader_bl_ = nullptr; -ShaderRoundPoint* TopoRender::shader_rp_ = nullptr; -int32 TopoRender::nb_instances_ = 0; - -TopoRender::TopoRender(QOpenGLFunctions_3_3_Core* ogl33): - ogl33_(ogl33), - dart_color_(255,255,255), - phi2_color_(255,0,0), - phi3_color_(255,255,0), - shrink_v_(0.6f), - shrink_f_(0.85f), - shrink_e_(0.95f) -{ - nb_instances_++; - - vbo_darts_ = new cgogn::rendering::VBO(3); - vbo_relations_ = new cgogn::rendering::VBO(3); - - if (!shader_bl_) - shader_bl_ = new ShaderBoldLine(); - vao_bl_ = shader_bl_->add_vao(); - shader_bl_->set_vao(vao_bl_,vbo_darts_); - vao_bl2_ = shader_bl_->add_vao(); - shader_bl_->set_vao(vao_bl2_,vbo_relations_); - - if (!shader_rp_) - shader_rp_ = new ShaderRoundPoint(); - vao_rp_ = shader_rp_->add_vao(); - shader_rp_->set_vao(vao_rp_,vbo_darts_,nullptr,2,0); - -} - -TopoRender::~TopoRender() -{ - delete vbo_darts_; - delete vbo_relations_; - - nb_instances_--; - if (nb_instances_ ==0) - { - // delete shaders when last TopoRender is deleted - // ensure context still enable when delete shaders - delete shader_rp_; - delete shader_bl_; - delete shader_cpv_; - } -} - -void TopoRender::draw(const QMatrix4x4& projection, const QMatrix4x4& modelview, bool with_blending) -{ - uint32 lw = 2.0; - if(with_blending) - { - ogl33_->glEnable(GL_BLEND); - ogl33_->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - lw = 3.0; - } - - shader_rp_->bind(); - shader_rp_->set_matrices(projection,modelview); - shader_rp_->set_width(2*lw); - shader_rp_->set_color(dart_color_); - shader_rp_->bind_vao(vao_rp_); - ogl33_->glDrawArrays(GL_POINTS,0,vbo_darts_->size()/2); - shader_rp_->release_vao(vao_rp_); - shader_rp_->release(); - - shader_bl_->bind(); - shader_bl_->set_matrices(projection,modelview); - shader_bl_->set_width(lw); - - shader_bl_->bind_vao(vao_bl_); - shader_bl_->set_color(dart_color_); - ogl33_->glDrawArrays(GL_LINES,0,vbo_darts_->size()); - shader_bl_->release_vao(vao_bl_); - - shader_bl_->bind_vao(vao_bl2_); - shader_bl_->set_color(phi2_color_); - ogl33_->glDrawArrays(GL_LINES,0,vbo_darts_->size()); - - if (vbo_relations_->size() > vbo_darts_->size()) - { - shader_bl_->set_color(phi3_color_); - ogl33_->glDrawArrays(GL_LINES,vbo_darts_->size(),vbo_darts_->size()); - } - shader_bl_->release_vao(vao_bl2_); - - shader_bl_->release(); - - ogl33_->glDisable(GL_BLEND); - -} - - - - -} // namespace rendering - -} // namespace cgogn diff --git a/cgogn/rendering/volume_drawer.cpp b/cgogn/rendering/volume_drawer.cpp new file mode 100644 index 00000000..8784d79d --- /dev/null +++ b/cgogn/rendering/volume_drawer.cpp @@ -0,0 +1,139 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#define CGOGN_RENDERING_DLL_EXPORT +#define CGOGN_RENDERING_VOLUME_RENDER_CPP_ + +#include + +#include +#include +#include + +namespace cgogn +{ + +namespace rendering +{ + +VolumeDrawerGen::VolumeDrawerGen(bool with_color_per_face): + vbo_pos_(nullptr), + vbo_col_(nullptr), + face_color_(0,150,0), + vbo_pos2_(nullptr), + edge_color_(0,0,0), + shrink_v_(0.6f) +{ + vbo_pos_ = cgogn::make_unique(3); + vbo_pos2_ = cgogn::make_unique(3); + + if (with_color_per_face) + vbo_col_ = cgogn::make_unique(3); +} + +VolumeDrawerGen::~VolumeDrawerGen() +{} + +VolumeDrawerGen::Renderer::Renderer(VolumeDrawerGen* vr): + param_expl_vol_(nullptr), + param_expl_vol_col_(nullptr), + param_expl_vol_line_(nullptr), + volume_drawer_data_(vr) +{ + if (vr->vbo_col_) + { + param_expl_vol_col_ = ShaderExplodeVolumesColor::generate_param(); + param_expl_vol_col_->explode_factor_ = vr->shrink_v_; + param_expl_vol_col_->set_all_vbos(vr->vbo_pos_.get(), vr->vbo_col_.get()); + } + else + { + param_expl_vol_ = ShaderExplodeVolumes::generate_param(); + param_expl_vol_->set_position_vbo(vr->vbo_pos_.get()); + param_expl_vol_->explode_factor_ = vr->shrink_v_; + param_expl_vol_->color_ = vr->face_color_; + } + + if (vr->vbo_pos2_) + { + param_expl_vol_line_ = ShaderExplodeVolumesLine::generate_param(); + param_expl_vol_line_->set_position_vbo(vr->vbo_pos2_.get()); + param_expl_vol_line_->explode_factor_ = vr->shrink_v_; + param_expl_vol_line_->color_ = vr->edge_color_; + } +} + +VolumeDrawerGen::Renderer::~Renderer() +{} + +void VolumeDrawerGen::Renderer::draw_faces(const QMatrix4x4& projection, const QMatrix4x4& modelview, QOpenGLFunctions_3_3_Core* ogl33) +{ + if (param_expl_vol_col_) + { + param_expl_vol_col_->bind(projection, modelview); + ogl33->glDrawArrays(GL_LINES_ADJACENCY, 0, volume_drawer_data_->vbo_pos_->size()); + param_expl_vol_col_->release(); + } + else + { + param_expl_vol_->bind(projection, modelview); + ogl33->glDrawArrays(GL_LINES_ADJACENCY, 0, volume_drawer_data_->vbo_pos_->size()); + param_expl_vol_->release(); + } +} + +void VolumeDrawerGen::Renderer::draw_edges(const QMatrix4x4& projection, const QMatrix4x4& modelview, QOpenGLFunctions_3_3_Core* ogl33) +{ + param_expl_vol_line_->bind(projection,modelview); + ogl33->glDrawArrays(GL_TRIANGLES, 0, volume_drawer_data_->vbo_pos2_->size()); + param_expl_vol_line_->release(); +} + +void VolumeDrawerGen::Renderer::set_explode_volume(float32 x) +{ + if (param_expl_vol_) + param_expl_vol_->explode_factor_ = x; + if (param_expl_vol_col_) + param_expl_vol_col_->explode_factor_ = x; + if (param_expl_vol_line_) + param_expl_vol_line_->explode_factor_ = x; +} + +void VolumeDrawerGen::Renderer::set_face_color(const QColor& rgb) +{ + if (param_expl_vol_) + param_expl_vol_->color_ = rgb; +} + +void VolumeDrawerGen::Renderer::set_edge_color(const QColor& rgb) +{ + if (param_expl_vol_line_) + param_expl_vol_line_->color_=rgb; +} + +template class CGOGN_RENDERING_API VolumeDrawerTpl; +template class CGOGN_RENDERING_API VolumeDrawerTpl; + +} // namespace rendering + +} // namespace cgogn diff --git a/cgogn/rendering/volume_drawer.h b/cgogn/rendering/volume_drawer.h new file mode 100644 index 00000000..d0ea171d --- /dev/null +++ b/cgogn/rendering/volume_drawer.h @@ -0,0 +1,340 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef CGOGN_RENDERING_VOLUME_RENDER_H_ +#define CGOGN_RENDERING_VOLUME_RENDER_H_ + +#include + +#include +#include +#include + +#include +#include + +#include +#include + +namespace cgogn +{ + +namespace rendering +{ +/** + * @brief Rendering ofvolumes + * + * Typical usage: + * + * std::unique_ptr volu_; // can be shared between contexts + * std::unique_ptr volu_rend_; // one by context, + * + * init: + * volu_ = cgogn::make_unique(); + * volu_rend_ = volu_->generate_renderer(); + * volu_->update_face(map_,vertex_position_); + * volu_->update_edge(map_,vertex_position_); + + * + * draw: + * volu_rend_->set_explode_volume(0.9); + * volu_rend_->draw_faces(proj,view,this); + * volu_rend_->draw_edges(proj,view,this); + * + */ +class CGOGN_RENDERING_API VolumeDrawerGen +{ +protected: + using Vec3f = std::array; + + std::unique_ptr vbo_pos_; + std::unique_ptr vbo_col_; + + QColor face_color_; + + std::unique_ptr vbo_pos2_; + QColor edge_color_; + + float32 shrink_v_; + float32 shrink_f_; + + void init_with_color(); + void init_without_color(); + void init_edge(); + +public: + + class CGOGN_RENDERING_API Renderer + { + friend class VolumeDrawerGen; + std::unique_ptr param_expl_vol_; + std::unique_ptr param_expl_vol_col_; + std::unique_ptr param_expl_vol_line_; + VolumeDrawerGen* volume_drawer_data_; + Renderer(VolumeDrawerGen* tr); + public: + ~Renderer(); + void draw_faces(const QMatrix4x4& projection, const QMatrix4x4& modelview, QOpenGLFunctions_3_3_Core* ogl33); + void draw_edges(const QMatrix4x4& projection, const QMatrix4x4& modelview, QOpenGLFunctions_3_3_Core* ogl33); + void set_explode_volume(float32 x); + void set_face_color(const QColor& rgb); + void set_edge_color(const QColor& rgb); + }; + + using Self = VolumeDrawerGen; + + /** + * constructor, init all buffers (data and OpenGL) and shader + * @Warning need OpenGL context + */ + VolumeDrawerGen(bool with_color_per_face); + + CGOGN_NOT_COPYABLE_NOR_MOVABLE(VolumeDrawerGen); + + /** + * release buffers and shader + */ + ~VolumeDrawerGen(); + + /** + * @brief generate a renderer (one per context) + * @return pointer on renderer + */ + inline std::unique_ptr generate_renderer() + { + return std::unique_ptr(new Renderer(this)); + } + + template + void update_edge(const MAP& m, const typename MAP::template VertexAttribute& position); + +}; + + +template +void VolumeDrawerGen::update_edge(const MAP& m, const typename MAP::template VertexAttribute& position) +{ + using Vertex = typename MAP::Vertex; + using Edge = typename MAP::Edge; + using Volume = typename MAP::Volume; + using Scalar = typename VEC3::Scalar; + + std::vector out_pos; + out_pos.reserve(1024 * 1024); + + std::vector ear_indices; + ear_indices.reserve(256); + + m.foreach_cell([&] (Volume v) + { + VEC3 CV = geometry::centroid(m, v, position); + m.foreach_incident_edge(v, [&] (Edge e) + { + const VEC3& P1 = position[Vertex(e.dart)]; + const VEC3& P2 = position[Vertex(m.phi1(e.dart))]; + out_pos.push_back({float32(CV[0]), float32(CV[1]), float32(CV[2])}); + out_pos.push_back({float32(P1[0]), float32(P1[1]), float32(P1[2])}); + out_pos.push_back({float32(P2[0]), float32(P2[1]), float32(P2[2])}); + }); + }); + + uint32 nbvec = uint32(out_pos.size()); + vbo_pos2_->allocate(nbvec, 3); + vbo_pos2_->bind(); + vbo_pos2_->copy_data(0, nbvec * 12, out_pos[0].data()); + vbo_pos2_->release(); +} + + +template +class VolumeDrawerTpl : public VolumeDrawerGen +{ +}; + + +template <> +class VolumeDrawerTpl : public VolumeDrawerGen +{ +public: + VolumeDrawerTpl(): VolumeDrawerGen(false) {} + + template + void update_face(const MAP& m, const typename MAP::template VertexAttribute& position) + { + using Vertex = typename MAP::Vertex; + using Face = typename MAP::Face; + using Volume = typename MAP::Volume; + using Scalar = typename VEC3::Scalar; + + std::vector out_pos; + out_pos.reserve(1024 * 1024); + + std::vector ear_indices; + ear_indices.reserve(256); + + m.foreach_cell([&] (Volume v) + { + VEC3 CV = geometry::centroid(m, v, position); + m.foreach_incident_face(v, [&] (Face f) + { + if (m.has_codegree(f, 3)) + { + const VEC3& P1 = position[Vertex(f.dart)]; + const VEC3& P2 = position[Vertex(m.phi1(f.dart))]; + const VEC3& P3 = position[Vertex(m.phi1(m.phi1(f.dart)))]; + out_pos.push_back({float32(CV[0]), float32(CV[1]), float32(CV[2])}); + out_pos.push_back({float32(P1[0]), float32(P1[1]), float32(P1[2])}); + out_pos.push_back({float32(P2[0]), float32(P2[1]), float32(P2[2])}); + out_pos.push_back({float32(P3[0]), float32(P3[1]), float32(P3[2])}); + } + else + { + ear_indices.clear(); + cgogn::geometry::compute_ear_triangulation(m, f, position, ear_indices); + for(std::size_t i = 0; i < ear_indices.size(); i += 3) + { + const VEC3& P1 = position[ear_indices[i]]; + const VEC3& P2 = position[ear_indices[i+1]]; + const VEC3& P3 = position[ear_indices[i+2]]; + out_pos.push_back({float32(CV[0]), float32(CV[1]), float32(CV[2])}); + out_pos.push_back({float32(P1[0]), float32(P1[1]), float32(P1[2])}); + out_pos.push_back({float32(P2[0]), float32(P2[1]), float32(P2[2])}); + out_pos.push_back({float32(P3[0]), float32(P3[1]), float32(P3[2])}); + } + } + }); + }); + + uint32 nbvec = uint32(out_pos.size()); + + vbo_pos_->allocate(nbvec, 3); + vbo_pos_->bind(); + vbo_pos_->copy_data(0, nbvec * 12, out_pos[0].data()); + vbo_pos_->release(); + } + +}; + + +template <> +class VolumeDrawerTpl : public VolumeDrawerGen +{ +public: + VolumeDrawerTpl(): VolumeDrawerGen(true) {} + + template + void update_face(const MAP& m, const typename MAP::template VertexAttribute& position, const typename MAP::template VertexAttribute& color) + { + using Vertex = typename MAP::Vertex; + using Face = typename MAP::Face; + using Volume = typename MAP::Volume; + using Scalar = typename VEC3::Scalar; + + std::vector out_pos; + out_pos.reserve(1024 * 1024); + + std::vector out_color; + out_color.reserve(1024 * 1024); + + std::vector ear_indices; + ear_indices.reserve(256); + + m.foreach_cell([&] (Volume v) + { + VEC3 CV = geometry::centroid(m, v, position); + m.foreach_incident_face(v, [&] (Face f) + { + if (m.has_codegree(f, 3)) + { + Dart d = f.dart; + const VEC3& P1 = position[Vertex(d)]; + const VEC3& C1 = color[Vertex(d)]; + d = m.phi1(d); + const VEC3& P2 = position[Vertex(d)]; + const VEC3& C2 = color[Vertex(d)]; + d = m.phi1(d); + const VEC3& P3 = position[Vertex(d)]; + const VEC3& C3 = color[Vertex(d)]; + out_pos.push_back({float32(CV[0]), float32(CV[1]), float32(CV[2])}); + out_pos.push_back({float32(P1[0]), float32(P1[1]), float32(P1[2])}); + out_pos.push_back({float32(P2[0]), float32(P2[1]), float32(P2[2])}); + out_pos.push_back({float32(P3[0]), float32(P3[1]), float32(P3[2])}); + out_color.push_back({float32(CV[0]), float32(CV[1]), float32(CV[2])}); + out_color.push_back({float32(C1[0]), float32(C1[1]), float32(C1[2])}); + out_color.push_back({float32(C2[0]), float32(C2[1]), float32(C2[2])}); + out_color.push_back({float32(C3[0]), float32(C3[1]), float32(C3[2])}); + } + else + { + ear_indices.clear(); + cgogn::geometry::compute_ear_triangulation(m, f,position,ear_indices); + for(std::size_t i = 0; i < ear_indices.size(); i += 3) + { + const VEC3& P1 = position[ear_indices[i]]; + const VEC3& C1 = color[ear_indices[i]]; + const VEC3& P2 = position[ear_indices[i+1]]; + const VEC3& C2 = color[ear_indices[i+1]]; + const VEC3& P3 = position[ear_indices[i+2]]; + const VEC3& C3 = color[ear_indices[i+2]]; + out_pos.push_back({float32(CV[0]), float32(CV[1]), float32(CV[2])}); + out_pos.push_back({float32(P1[0]), float32(P1[1]), float32(P1[2])}); + out_pos.push_back({float32(P2[0]), float32(P2[1]), float32(P2[2])}); + out_pos.push_back({float32(P3[0]), float32(P3[1]), float32(P3[2])}); + out_color.push_back({float32(CV[0]), float32(CV[1]), float32(CV[2])}); + out_color.push_back({float32(C1[0]), float32(C1[1]), float32(C1[2])}); + out_color.push_back({float32(C2[0]), float32(C2[1]), float32(C2[2])}); + out_color.push_back({float32(C3[0]), float32(C3[1]), float32(C3[2])}); + } + } + }); + }); + + std::size_t nbvec = out_pos.size(); + + vbo_pos_->allocate(nbvec, 3); + vbo_pos_->bind(); + vbo_pos_->copy_data(0, nbvec * 12, out_pos[0].data()); + vbo_pos_->release(); + + vbo_col_->allocate(nbvec, 3); + vbo_col_->bind(); + vbo_col_->copy_data(0, nbvec * 12, out_color[0].data()); + vbo_col_->release(); + } + +}; + + +using VolumeDrawer = VolumeDrawerTpl; +using VolumeDrawerColor = VolumeDrawerTpl; + +#if !defined(CGOGN_RENDERING_VOLUME_RENDER_CPP_) +extern template class CGOGN_RENDERING_API VolumeDrawerTpl; +extern template class CGOGN_RENDERING_API VolumeDrawerTpl; +#endif // (!defined(CGOGN_RENDERING_VOLUME_RENDER_CPP_)) + +} // namespace rendering + +} // namespace cgogn + +#endif // CGOGN_RENDERING_VOLUME_RENDER_H_ diff --git a/cgogn/rendering/volume_render.cpp b/cgogn/rendering/volume_render.cpp deleted file mode 100644 index 005fe56e..00000000 --- a/cgogn/rendering/volume_render.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/******************************************************************************* -* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * -* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * -* * -* This library is free software; you can redistribute it and/or modify it * -* under the terms of the GNU Lesser General Public License as published by the * -* Free Software Foundation; either version 2.1 of the License, or (at your * -* option) any later version. * -* * -* This library is distributed in the hope that it will be useful, but WITHOUT * -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * -* for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with this library; if not, write to the Free Software Foundation, * -* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * -* * -* Web site: http://cgogn.unistra.fr/ * -* Contact information: cgogn@unistra.fr * -* * -*******************************************************************************/ - -#define CGOGN_RENDERING_DLL_EXPORT - -#include - -#include -#include -#include - -namespace cgogn -{ - -namespace rendering -{ - - - -VolumeRender::VolumeRender(QOpenGLFunctions_3_3_Core* ogl33): - shader_expl_vol_(nullptr), - shader_expl_vol_line_(nullptr), - vbo_col_(nullptr), - ogl33_(ogl33), - face_color_(0,150,0), - edge_color_(0,0,0), - shrink_v_(0.6f), - shrink_f_(0.85f) -{ - vbo_pos_ = new cgogn::rendering::VBO(3); -} - -void VolumeRender::init_with_color() -{ - if ((vbo_col_!= nullptr) && (shader_expl_vol_!= nullptr)) - return; - - vbo_col_ = new cgogn::rendering::VBO(3); - - delete shader_expl_vol_; - shader_expl_vol_ = new ShaderExplodeVolumes(true); - vao1_ = shader_expl_vol_->add_vao(); - shader_expl_vol_->set_vao(vao1_,vbo_pos_,vbo_col_); -} - -void VolumeRender::init_without_color() -{ - if ((vbo_col_== nullptr) && (shader_expl_vol_!= nullptr)) - return; - - delete vbo_col_; - vbo_col_ = nullptr; - - delete shader_expl_vol_; - shader_expl_vol_ = new ShaderExplodeVolumes(false); - vao1_ = shader_expl_vol_->add_vao(); - shader_expl_vol_->set_vao(vao1_,vbo_pos_,vbo_col_); -} - -void VolumeRender::init_edge() -{ - if (shader_expl_vol_line_!= nullptr) - return; - - vbo_pos2_ = new cgogn::rendering::VBO(3); - - shader_expl_vol_line_ = new ShaderExplodeVolumesLine(); - vao2_ = shader_expl_vol_line_->add_vao(); - shader_expl_vol_line_->set_vao(vao2_,vbo_pos2_); -} - - -VolumeRender::~VolumeRender() -{ - delete vbo_pos_; - delete vbo_col_; - delete shader_expl_vol_; -} - -void VolumeRender::draw_faces(const QMatrix4x4& projection, const QMatrix4x4& modelview) -{ - shader_expl_vol_->bind(); - shader_expl_vol_->set_matrices(projection,modelview); - shader_expl_vol_->set_explode_volume(shrink_v_); - shader_expl_vol_->set_color(face_color_); - shader_expl_vol_->bind_vao(vao1_); - ogl33_->glDrawArrays(GL_LINES_ADJACENCY,0,vbo_pos_->size()); - shader_expl_vol_->release_vao(vao1_); - shader_expl_vol_->release(); -} - -void VolumeRender::draw_edges(const QMatrix4x4& projection, const QMatrix4x4& modelview) -{ - shader_expl_vol_line_->bind(); - shader_expl_vol_line_->set_matrices(projection,modelview); - shader_expl_vol_line_->set_explode_volume(shrink_v_); - shader_expl_vol_line_->set_color(edge_color_); - shader_expl_vol_line_->bind_vao(vao2_); - ogl33_->glDrawArrays(GL_TRIANGLES,0,vbo_pos2_->size()); - shader_expl_vol_line_->release_vao(vao2_); - shader_expl_vol_line_->release(); -} - - - -} // namespace rendering - -} // namespace cgogn diff --git a/cgogn/rendering/volume_render.h b/cgogn/rendering/volume_render.h deleted file mode 100644 index 8a0eb9e9..00000000 --- a/cgogn/rendering/volume_render.h +++ /dev/null @@ -1,298 +0,0 @@ -/******************************************************************************* -* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * -* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * -* * -* This library is free software; you can redistribute it and/or modify it * -* under the terms of the GNU Lesser General Public License as published by the * -* Free Software Foundation; either version 2.1 of the License, or (at your * -* option) any later version. * -* * -* This library is distributed in the hope that it will be useful, but WITHOUT * -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * -* for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with this library; if not, write to the Free Software Foundation, * -* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * -* * -* Web site: http://cgogn.unistra.fr/ * -* Contact information: cgogn@unistra.fr * -* * -*******************************************************************************/ - -#ifndef RENDERING_VOLUME_RENDER_H_ -#define RENDERING_VOLUME_RENDER_H_ - -#include -#include -#include -#include -#include -#include - -#include -#include - -namespace cgogn -{ - -namespace rendering -{ - - -class CGOGN_RENDERING_API VolumeRender -{ - using Vec3f = std::array; - -protected: - - ShaderExplodeVolumes* shader_expl_vol_; - - ShaderExplodeVolumesLine* shader_expl_vol_line_; - - VBO* vbo_pos_; - VBO* vbo_col_; - uint32 vao1_; - QColor face_color_; - - - VBO* vbo_pos2_; - uint32 vao2_; - QColor edge_color_; - - - QOpenGLFunctions_3_3_Core* ogl33_; - - float32 shrink_v_; - float32 shrink_f_; - - void init_with_color(); - - void init_without_color(); - - void init_edge(); - -public: - using Self = VolumeRender; - CGOGN_NOT_COPYABLE_NOR_MOVABLE(VolumeRender); - /** - * constructor, init all buffers (data and OpenGL) and shader - * @Warning need OpenGL context - */ - VolumeRender(QOpenGLFunctions_3_3_Core* ogl33); - - /** - * release buffers and shader - */ - ~VolumeRender(); - - inline void set_explode_face(float32 x) { shrink_f_ = x; } - - inline void set_explode_volume(float32 x) { shrink_v_ = x; } - - inline void set_face_color(const QColor& rgb) { face_color_= rgb; } - - inline void set_edge_color(const QColor& rgb) { edge_color_= rgb; } - - template - void update_face(MAP& m, const typename MAP::template VertexAttributeHandler& position); - - template - void update_face(MAP& m, const typename MAP::template VertexAttributeHandler& position, - const typename MAP::template VertexAttributeHandler& color); - - template - void update_edge(MAP& m, const typename MAP::template VertexAttributeHandler& position); - - void draw_faces(const QMatrix4x4& projection, const QMatrix4x4& modelview); - - void draw_edges(const QMatrix4x4& projection, const QMatrix4x4& modelview); -}; - - -template -void VolumeRender::update_face(MAP& m, const typename MAP::template VertexAttributeHandler& position) -{ - init_without_color(); - - using Vertex = typename MAP::Vertex; - using Face = typename MAP::Face; - using Volume = typename MAP::Volume; - using Scalar = typename VEC3::Scalar; - - std::vector> out_pos; - out_pos.reserve(1024*1024); - - std::vector ear_indices; - ear_indices.reserve(256); - - m.foreach_cell([&] (Volume v) - { - VEC3 CV = geometry::centroid(m, v, position); - m.foreach_incident_face(v, [&] (Face f) - { - if (m.has_codegree(f, 3)) - { - const VEC3& P1 = position[Vertex(f.dart)]; - const VEC3& P2 = position[Vertex(m.phi1(f.dart))]; - const VEC3& P3 = position[Vertex(m.phi1(m.phi1(f.dart)))]; - out_pos.push_back({float32(CV[0]),float32(CV[1]),float32(CV[2])}); - out_pos.push_back({float32(P1[0]),float32(P1[1]),float32(P1[2])}); - out_pos.push_back({float32(P2[0]),float32(P2[1]),float32(P2[2])}); - out_pos.push_back({float32(P3[0]),float32(P3[1]),float32(P3[2])}); - } - else - { - ear_indices.clear(); - cgogn::geometry::compute_ear_triangulation(m,f,position,ear_indices); - for(std::size_t i = 0; i < ear_indices.size(); i += 3) - { - const VEC3& P1 = position[ear_indices[i]]; - const VEC3& P2 = position[ear_indices[i+1]]; - const VEC3& P3 = position[ear_indices[i+2]]; - out_pos.push_back({float32(CV[0]),float32(CV[1]),float32(CV[2])}); - out_pos.push_back({float32(P1[0]),float32(P1[1]),float32(P1[2])}); - out_pos.push_back({float32(P2[0]),float32(P2[1]),float32(P2[2])}); - out_pos.push_back({float32(P3[0]),float32(P3[1]),float32(P3[2])}); - } - } - }); - }); - - uint32 nbvec = std::uint32_t(out_pos.size()); - vbo_pos_->allocate(nbvec,3); - vbo_pos_->bind(); - vbo_pos_->copy_data(0, nbvec*12, out_pos[0].data()); - vbo_pos_->release(); - -} - -template -void VolumeRender::update_face(MAP& m, const typename MAP::template VertexAttributeHandler& position, - const typename MAP::template VertexAttributeHandler& color) -{ - init_with_color(); - - using Vertex = typename MAP::Vertex; - using Face = typename MAP::Face; - using Volume = typename MAP::Volume; - using Scalar = typename VEC3::Scalar; - - std::vector> out_pos; - out_pos.reserve(1024*1024); - - std::vector> out_color; - out_color.reserve(1024*1024); - - std::vector ear_indices; - ear_indices.reserve(256); - - m.foreach_cell([&] (Volume v) - { - VEC3 CV = geometry::centroid(m,v,position); - m.foreach_incident_face(v, [&] (Face f) - { - if (m.has_degree(f,3)) - { - Dart d = f.dart; - const VEC3& P1 = position[Vertex(d)]; - const VEC3& C1 = color[Vertex(d)]; - d = m.phi1(d); - const VEC3& P2 = position[Vertex(d)]; - const VEC3& C2 = color[Vertex(d)]; - d = m.phi1(d); - const VEC3& P3 = position[Vertex(d)]; - const VEC3& C3 = color[Vertex(d)]; - out_pos.push_back({float32(CV[0]),float32(CV[1]),float32(CV[2])}); - out_pos.push_back({float32(P1[0]),float32(P1[1]),float32(P1[2])}); - out_pos.push_back({float32(P2[0]),float32(P2[1]),float32(P2[2])}); - out_pos.push_back({float32(P3[0]),float32(P3[1]),float32(P3[2])}); - out_color.push_back({float32(CV[0]),float32(CV[1]),float32(CV[2])}); - out_color.push_back({float32(C1[0]),float32(C1[1]),float32(C1[2])}); - out_color.push_back({float32(C2[0]),float32(C2[1]),float32(C2[2])}); - out_color.push_back({float32(C3[0]),float32(C3[1]),float32(C3[2])}); - } - else - { - ear_indices.clear(); - cgogn::geometry::compute_ear_triangulation(m,f,position,ear_indices); - for(std::size_t i=0; iallocate(nbvec,3); - vbo_pos_->bind(); - vbo_pos_->copy_data(0, nbvec*12, out_pos[0].data()); - vbo_pos_->release(); - - vbo_col_->allocate(nbvec,3); - vbo_col_->bind(); - vbo_col_->copy_data(0, nbvec*12, out_color[0].data()); - vbo_col_->release(); - -} - - - -template -void VolumeRender::update_edge(MAP& m, const typename MAP::template VertexAttributeHandler& position) -{ - init_edge(); - - using Vertex = typename MAP::Vertex; - using Edge = typename MAP::Edge; - using Volume = typename MAP::Volume; - using Scalar = typename VEC3::Scalar; - - std::vector> out_pos; - out_pos.reserve(1024*1024); - - std::vector ear_indices; - ear_indices.reserve(256); - - m.foreach_cell([&] (Volume v) - { - VEC3 CV = geometry::centroid(m,v,position); - m.foreach_incident_edge(v, [&] (Edge e) - { - const VEC3& P1 = position[Vertex(e.dart)]; - const VEC3& P2 = position[Vertex(m.phi1(e.dart))]; - out_pos.push_back({float32(CV[0]),float32(CV[1]),float32(CV[2])}); - out_pos.push_back({float32(P1[0]),float32(P1[1]),float32(P1[2])}); - out_pos.push_back({float32(P2[0]),float32(P2[1]),float32(P2[2])}); - }); - }); - - uint32 nbvec = std::uint32_t(out_pos.size()); - vbo_pos2_->allocate(nbvec,3); - vbo_pos2_->bind(); - vbo_pos2_->copy_data(0, nbvec*12, out_pos[0].data()); - vbo_pos2_->release(); -} - - -} // namespace rendering - -} // namespace cgogn - -#endif // RENDERING_VOLUME_RENDER_H_ diff --git a/cgogn/rendering/wall_paper.cpp b/cgogn/rendering/wall_paper.cpp new file mode 100644 index 00000000..54da7333 --- /dev/null +++ b/cgogn/rendering/wall_paper.cpp @@ -0,0 +1,168 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#define CGOGN_RENDERING_DLL_EXPORT + +#include + +#include +#include + + +namespace cgogn +{ + +namespace rendering +{ + +WallPaper::WallPaper(const QImage& img) +{ + vbo_pos_ = cgogn::make_unique(3); + vbo_pos_->allocate(4,3); + vbo_tc_ = cgogn::make_unique(2); + vbo_tc_->allocate(4,2); + + texture_ = cgogn::make_unique(img); + + set_full_screen(false); + + float32* ptr_tc = vbo_tc_->lock_pointer(); + *ptr_tc++ = 0.0f; + *ptr_tc++ = 0.0f; + *ptr_tc++ = 1.0f; + *ptr_tc++ = 0.0f; + *ptr_tc++ = 1.0f; + *ptr_tc++ = 1.0f; + *ptr_tc++ = 0.0f; + *ptr_tc++ = 1.0f; + vbo_tc_->release_pointer(); +} + +WallPaper::~WallPaper() +{} + +void WallPaper::set_full_screen(bool front) +{ + float32 depth = 0.9999999f; + if (front) + depth = 0.0f; + + float32* ptr_pos = vbo_pos_->lock_pointer(); + *ptr_pos++ = -1.0f; + *ptr_pos++ = 1.0f; + *ptr_pos++ = depth; + *ptr_pos++ = 1.0f; + *ptr_pos++ = 1.0f; + *ptr_pos++ = depth; + *ptr_pos++ = 1.0f; + *ptr_pos++ = -1.0f; + *ptr_pos++ = depth; + *ptr_pos++ = -1.0f; + *ptr_pos++ = -1.0f; + *ptr_pos++ = depth; + vbo_pos_->release_pointer(); +} + + +void WallPaper::set_local_position(uint32 win_w, uint32 win_h, uint32 x, uint32 y, uint32 w, uint32 h, bool front) +{ + float32 depth = 0.0f; + if (!front) + depth = 0.9999999f; + + float32 xmin = -1.0f + float32(2*x)/float32(win_w); + float32 xmax = xmin + float32(2*w)/float32(win_w); + + float32 ymin = 1.0f - float32(2*y)/float32(win_h); + float32 ymax = ymin - float32(2*h)/float32(win_h); + + float32* ptr_pos = vbo_pos_->lock_pointer(); + *ptr_pos++ = xmin; + *ptr_pos++ = ymin; + *ptr_pos++ = depth; + *ptr_pos++ = xmax; + *ptr_pos++ = ymin; + *ptr_pos++ = depth; + *ptr_pos++ = xmax; + *ptr_pos++ = ymax; + *ptr_pos++ = depth; + *ptr_pos++ = xmin; + *ptr_pos++ = ymax; + *ptr_pos++ = depth; + vbo_pos_->release_pointer(); +} + + +void WallPaper::set_local_position(float x, float y, float w, float h, bool front) +{ + float32 depth = 0.0f; + if (!front) + depth = 0.9999999f; + + float32 xmin = -1.0f + 2*x; + float32 xmax = xmin + 2*w; + + float32 ymin = 1.0f - 2*y; + float32 ymax = ymin - 2*h; + + float32* ptr_pos = vbo_pos_->lock_pointer(); + *ptr_pos++ = xmin; + *ptr_pos++ = ymin; + *ptr_pos++ = depth; + *ptr_pos++ = xmax; + *ptr_pos++ = ymin; + *ptr_pos++ = depth; + *ptr_pos++ = xmax; + *ptr_pos++ = ymax; + *ptr_pos++ = depth; + *ptr_pos++ = xmin; + *ptr_pos++ = ymax; + *ptr_pos++ = depth; + vbo_pos_->release_pointer(); +} + +WallPaper::Renderer::Renderer(WallPaper* wp): + wall_paper_data_(wp) +{ + param_texture_ = ShaderTexture::generate_param(); + param_texture_->set_vbo(wp->vbo_pos_.get(), wp->vbo_tc_.get()); + param_texture_->texture_ = wp->texture_.get(); +} + +WallPaper::Renderer::~Renderer() +{} + + +void WallPaper::Renderer::draw(QOpenGLFunctions_3_3_Core* ogl33) +{ + QMatrix4x4 id; + param_texture_->bind(id,id); + ogl33->glDrawArrays(GL_TRIANGLE_FAN,0,4); + param_texture_->release(); +} + + + +} // namespace rendering + +} // namespace cgogn diff --git a/cgogn/rendering/wall_paper.h b/cgogn/rendering/wall_paper.h new file mode 100644 index 00000000..78fd5517 --- /dev/null +++ b/cgogn/rendering/wall_paper.h @@ -0,0 +1,135 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef CGOGN_RENDERING_WALL_PAPER_H_ +#define CGOGN_RENDERING_WALL_PAPER_H_ + +#include +#include +#include +#include + +namespace cgogn +{ + +namespace rendering +{ + +/** + * @brief WallPaper: allow rendering of a texture, front or back, full-screen or not + * + * Typical usage: + * + * std::unique_ptr wp_; // can be shared between contexts + * std::unique_ptr wp_rend_; // one by context, + * + * init: + * wp_ = cgogn::make_unique(); + * wp_rend_ = wp_->generate_renderer(); + * wp_->update(map_,vertex_position_); + * + * draw: + * wp_rend_->draw(proj,view,this); + * + */ +class CGOGN_RENDERING_API WallPaper +{ +protected: + std::unique_ptr vbo_pos_; + std::unique_ptr vbo_tc_; + std::unique_ptr texture_; + +public: + class CGOGN_RENDERING_API Renderer + { + friend class WallPaper; + std::unique_ptr param_texture_; + WallPaper* wall_paper_data_; + Renderer(WallPaper* wp); + public: + ~Renderer(); + void draw(QOpenGLFunctions_3_3_Core* ogl33); + }; + + using Self = WallPaper; + CGOGN_NOT_COPYABLE_NOR_MOVABLE(WallPaper); + + /** + * constructor, init all buffers (data and OpenGL) and shader + * @Warning need OpenGL context + */ + WallPaper(const QImage& img); + + /** + * release buffers and shader + */ + ~WallPaper(); + + /** + * @brief generate a renderer (one per context) + * @return pointer on renderer + */ + inline std::unique_ptr generate_renderer() + { + return std::unique_ptr(new Renderer(this)); + } + + /** + * @brief set the texture in full screen + * @param front if true draw with depth of 0 (front) else with depth of ~1 (back) + */ + void set_full_screen(bool front = false); + + /** + * @brief set a local position for the image in pixel + * @warning position & size are converted in % when set, and used even when window size has changed + * @param win_w width of window + * @param win_h height of window + * @param x x pos (0 is left) + * @param y y pos (0 is top) + * @param w width to draw + * @param h height to draw + * @param front (default is back drawing) + */ + void set_local_position(uint32 win_w, uint32 win_h, uint32 x, uint32 y, uint32 w, uint32 h, bool front = true); + + /** + * @brief set a local position for the image in ratio ([0-1]) of the viewport + * @param x x pos (0.0 is left) + * @param y y pos (0 is top) + * @param w width to draw + * @param h height to draw + * @param front (default is front drawing) + */ + void set_local_position(float x, float y, float w, float h, bool front = true); + + void draw(QOpenGLFunctions_3_3_Core* ogl33); +}; + + + +} // namespace rendering + +} // namespace cgogn + +#endif // CGOGN_RENDERING_WALL_PAPER_H_ diff --git a/cmake/CompilerOptions.cmake b/cmake/CompilerOptions.cmake index 5102b61c..9fa5dfe9 100644 --- a/cmake/CompilerOptions.cmake +++ b/cmake/CompilerOptions.cmake @@ -130,5 +130,6 @@ else() # MSVC # C4910 - __declspec(dllexport)' and 'extern' are incompatible on an explicit instantiation # C4251 - 'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2' add_flags(CMAKE_CXX_FLAGS "/EHsc /wd4127 /wd4505 /wd4714 /wd4910 /wd4251 /bigobj") + add_definitions("/DNOMINMAX") endif() diff --git a/cmake/ConfigFiles/QOGLViewerConfig.cmake.in b/cmake/ConfigFiles/QOGLViewerConfig.cmake.in new file mode 100644 index 00000000..482b2644 --- /dev/null +++ b/cmake/ConfigFiles/QOGLViewerConfig.cmake.in @@ -0,0 +1,10 @@ +@PACKAGE_INIT@ + +set(QOGLViewer_LIBRARIES "QOGLViewer") +set(QOGLViewer_INCLUDE_DIRS "@PACKAGE_QOGLVIEWER_INCLUDE_DIR@") + +if(NOT TARGET QOGLViewer) + include("${CMAKE_CURRENT_LIST_DIR}/QOGLViewerTargets.cmake") +endif() + +check_required_components(QOGLViewer) diff --git a/cmake/ConfigFiles/cgogn_coreConfig.cmake.in b/cmake/ConfigFiles/cgogn_coreConfig.cmake.in new file mode 100644 index 00000000..0333a19c --- /dev/null +++ b/cmake/ConfigFiles/cgogn_coreConfig.cmake.in @@ -0,0 +1,10 @@ +@PACKAGE_INIT@ + +set(cgogn_core_LIBRARIES "cgogn_core") +set(cgogn_core_INCLUDE_DIRS "@PACKAGE_CGOGN_CORE_INCLUDE_DIRS@") + +if(NOT TARGET cgogn_core) + include("${CMAKE_CURRENT_LIST_DIR}/cgogn_coreTargets.cmake") +endif() + +check_required_components(cgogn_core) \ No newline at end of file diff --git a/cmake/ConfigFiles/cgogn_geometryConfig.cmake.in b/cmake/ConfigFiles/cgogn_geometryConfig.cmake.in new file mode 100644 index 00000000..08ef444b --- /dev/null +++ b/cmake/ConfigFiles/cgogn_geometryConfig.cmake.in @@ -0,0 +1,12 @@ +@PACKAGE_INIT@ + +find_package(cgogn_core REQUIRED) + +set(cgogn_geometry_LIBRARIES "cgogn_geometry") +set(cgogn_geometry_INCLUDE_DIRS "@PACKAGE_CGOGN_GEOMETRY_INCLUDE_DIRS@") + +if(NOT TARGET cgogn_geometry) + include("${CMAKE_CURRENT_LIST_DIR}/cgogn_geometryTargets.cmake") +endif() + +check_required_components(cgogn_core cgogn_geometry) \ No newline at end of file diff --git a/cmake/ConfigFiles/cgogn_ioConfig.cmake.in b/cmake/ConfigFiles/cgogn_ioConfig.cmake.in new file mode 100644 index 00000000..c318f7ab --- /dev/null +++ b/cmake/ConfigFiles/cgogn_ioConfig.cmake.in @@ -0,0 +1,17 @@ +@PACKAGE_INIT@ + +find_package(ZLIB) +find_package(cgogn_core REQUIRED) +find_package(cgogn_geometry REQUIRED) +find_package(ply REQUIRED) +find_package(lm6 REQUIRED) +find_package(tinyxml2 REQUIRED) + +set(cgogn_io_LIBRARIES "cgogn_io") +set(cgogn_io_INCLUDE_DIRS "@PACKAGE_CGOGN_IO_INCLUDE_DIRS@") + +if(NOT TARGET cgogn_io) + include("${CMAKE_CURRENT_LIST_DIR}/cgogn_ioTargets.cmake") +endif() + +check_required_components(cgogn_core cgogn_geometry cgogn_io) \ No newline at end of file diff --git a/cmake/ConfigFiles/cgogn_multiresolutionConfig.cmake.in b/cmake/ConfigFiles/cgogn_multiresolutionConfig.cmake.in new file mode 100644 index 00000000..95fca9b2 --- /dev/null +++ b/cmake/ConfigFiles/cgogn_multiresolutionConfig.cmake.in @@ -0,0 +1,13 @@ +@PACKAGE_INIT@ + +find_package(cgogn_core REQUIRED) +find_package(cgogn_geometry REQUIRED) + +set(cgogn_multiresolution_LIBRARIES "cgogn_multiresolution") +set(cgogn_multiresolution_INCLUDE_DIRS "@PACKAGE_CGOGN_MULTIRESOLUTION_INCLUDE_DIRS@") + +if(NOT TARGET cgogn_multiresolution) + include("${CMAKE_CURRENT_LIST_DIR}/cgogn_multiresolutionTargets.cmake") +endif() + +check_required_components(cgogn_core cgogn_geometry cgogn_multiresolution) \ No newline at end of file diff --git a/cmake/ConfigFiles/cgogn_renderingConfig.cmake.in b/cmake/ConfigFiles/cgogn_renderingConfig.cmake.in new file mode 100644 index 00000000..b659bfde --- /dev/null +++ b/cmake/ConfigFiles/cgogn_renderingConfig.cmake.in @@ -0,0 +1,14 @@ +@PACKAGE_INIT@ + +find_package(cgogn_core REQUIRED) +find_package(cgogn_geometry REQUIRED) +find_package(Qt5Widgets) + +set(cgogn_rendering_LIBRARIES "cgogn_rendering") +set(cgogn_rendering_INCLUDE_DIRS "@PACKAGE_CGOGN_RENDERING_INCLUDE_DIRS@") + +if(NOT TARGET cgogn_rendering) + include("${CMAKE_CURRENT_LIST_DIR}/cgogn_renderingTargets.cmake") +endif() + +check_required_components(cgogn_core cgogn_geometry Qt5::Widgets) \ No newline at end of file diff --git a/cmake/ConfigFiles/lm6Config.cmake.in b/cmake/ConfigFiles/lm6Config.cmake.in new file mode 100644 index 00000000..bb7e95a2 --- /dev/null +++ b/cmake/ConfigFiles/lm6Config.cmake.in @@ -0,0 +1,10 @@ +@PACKAGE_INIT@ + +set(lm6_LIBRARIES "lm6") +set(lm6_INCLUDE_DIRS "@PACKAGE_LM6_INCLUDE_DIR@") + +if(NOT TARGET lm6) + include("${CMAKE_CURRENT_LIST_DIR}/lm6Targets.cmake") +endif() + +check_required_components(lm6) \ No newline at end of file diff --git a/cmake/ConfigFiles/plyConfig.cmake.in b/cmake/ConfigFiles/plyConfig.cmake.in new file mode 100644 index 00000000..460094c3 --- /dev/null +++ b/cmake/ConfigFiles/plyConfig.cmake.in @@ -0,0 +1,10 @@ +@PACKAGE_INIT@ + +set(ply_LIBRARIES "ply") +set(ply_INCLUDE_DIRS "@PACKAGE_PLY_INCLUDE_DIR@") + +if(NOT TARGET ply) + include("${CMAKE_CURRENT_LIST_DIR}/plyTargets.cmake") +endif() + +check_required_components(ply) \ No newline at end of file diff --git a/cmake/ConfigFiles/tetConfig.cmake.in b/cmake/ConfigFiles/tetConfig.cmake.in new file mode 100644 index 00000000..76ac23f0 --- /dev/null +++ b/cmake/ConfigFiles/tetConfig.cmake.in @@ -0,0 +1,10 @@ +@PACKAGE_INIT@ + +set(tet_LIBRARIES "tet") +set(tet_INCLUDE_DIRS "@PACKAGE_TET_INCLUDE_DIR@") + +if(NOT TARGET tet) + include("${CMAKE_CURRENT_LIST_DIR}/tetTargets.cmake") +endif() + +check_required_components(tet) \ No newline at end of file diff --git a/cmake/ConfigFiles/tinyxml2Config.cmake.in b/cmake/ConfigFiles/tinyxml2Config.cmake.in new file mode 100644 index 00000000..d50f11b2 --- /dev/null +++ b/cmake/ConfigFiles/tinyxml2Config.cmake.in @@ -0,0 +1,10 @@ +@PACKAGE_INIT@ + +set(tinyxml2_LIBRARIES "tinyxml2") +set(tinyxml2_INCLUDE_DIRS "@PACKAGE_TINYXML2_INCLUDE_DIR@") + +if(NOT TARGET tinyxml2) + include("${CMAKE_CURRENT_LIST_DIR}/tinyxml2Targets.cmake") +endif() + +check_required_components(tinyxml2) \ No newline at end of file diff --git a/cmake/utilities.cmake b/cmake/utilities.cmake index 9aa99657..8c0adb63 100644 --- a/cmake/utilities.cmake +++ b/cmake/utilities.cmake @@ -9,6 +9,13 @@ function(add_flags _var) set(${_var} ${string} PARENT_SCOPE) endfunction() +function(remove_flags _var) + string(REPLACE " " ";" flags "${${_var}}") + list(REMOVE_ITEM flags ${ARGN}) + string(REPLACE ";" " " flags "${flags}") + set(${_var} ${flags} PARENT_SCOPE) +endfunction() + #! # @brief Add sources from directories # @details @@ -49,3 +56,83 @@ else() endif() endif() endfunction(deduce_build_type) + +############################################################################################## +# cgogn_create_package macro # +# This macro is a helper to create package configuration and version files. These files are # +# needed when using the find_package command. # +# This macro generate 2 versions of each file : one for the build tree and another for the # +# install tree. # +# Build tree: # +# 1./lib/cmake//Targets.cmake # +# 2./lib/cmake//Config.cmake # +# 3./lib/cmake//ConfigVersion.cmake # +# # +# Install tree: # +# 1./lib/cmake//Targets.cmake # +# 2./lib/cmake//Config.cmake # +# 3./lib/cmake//ConfigVersion.cmake # +# # +# Usage example : find_package(cgogn_core); find_package(cgogn_io) # +# Note: template config files are located in the cmake/ConfigFiles directory. # +# By convention they have to define the following two variables: # +# cmake/_LIBRARIES # +# cmake/_INCLUDE_DIRS # +############################################################################################## + +macro(cgogn_create_package include_dirs_build_tree include_dirs_install_tree) + +######## 1. Build tree + +set(UPPER_NAME "") +string(TOUPPER ${PROJECT_NAME} UPPER_NAME) +set(${UPPER_NAME}_INCLUDE_DIRS ${include_dirs_build_tree}) + +export(TARGETS ${PROJECT_NAME} +FILE "${CMAKE_BINARY_DIR}/lib/cmake/${PROJECT_NAME}/${PROJECT_NAME}Targets.cmake") + +configure_package_config_file( + "${CGOGN_PATH}/cmake/ConfigFiles/${PROJECT_NAME}Config.cmake.in" + "${CMAKE_BINARY_DIR}/lib/cmake/${PROJECT_NAME}/${PROJECT_NAME}Config.cmake" + PATH_VARS ${UPPER_NAME}_INCLUDE_DIRS + INSTALL_DESTINATION "${CMAKE_BINARY_DIR}/lib/cmake/${PROJECT_NAME}" +) + +write_basic_package_version_file( + "${CMAKE_BINARY_DIR}/lib/cmake/${PROJECT_NAME}/${PROJECT_NAME}ConfigVersion.cmake" + VERSION ${CGOGN_VERSION_MAJOR}.${CGOGN_VERSION_MINOR}.${CGOGN_VERSION_PATCH} + COMPATIBILITY ExactVersion +) + +######## 2. Install tree + +set(${UPPER_NAME}_INCLUDE_DIRS ${include_dirs_install_tree}) + +install(TARGETS ${PROJECT_NAME} + EXPORT ${PROJECT_NAME}Targets + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib +) +install(EXPORT ${PROJECT_NAME}Targets DESTINATION "lib/cmake/${PROJECT_NAME}") + +## ConfigVersion.cmake +write_basic_package_version_file( + "${CMAKE_BINARY_DIR}/share/cmake/${PROJECT_NAME}/${PROJECT_NAME}ConfigVersion.cmake" + VERSION ${CGOGN_VERSION_MAJOR}.${CGOGN_VERSION_MINOR}.${CGOGN_VERSION_PATCH} + COMPATIBILITY ExactVersion +) + +## Config.cmake +set(CURRENT_LIBRARY "${PROJECT_NAME}") +configure_package_config_file( + "${CGOGN_PATH}/cmake/ConfigFiles/${PROJECT_NAME}Config.cmake.in" + "${CMAKE_BINARY_DIR}/share/cmake/${PROJECT_NAME}/${PROJECT_NAME}InstallConfig.cmake" + PATH_VARS ${UPPER_NAME}_INCLUDE_DIRS + INSTALL_DESTINATION "lib/cmake/${PROJECT_NAME}" +) + +install(FILES "${CMAKE_BINARY_DIR}/share/cmake/${PROJECT_NAME}/${PROJECT_NAME}ConfigVersion.cmake" DESTINATION "lib/cmake/${PROJECT_NAME}") +install(FILES "${CMAKE_BINARY_DIR}/share/cmake/${PROJECT_NAME}/${PROJECT_NAME}InstallConfig.cmake" DESTINATION "lib/cmake/${PROJECT_NAME}" RENAME "${PROJECT_NAME}Config.cmake") + +endmacro() diff --git a/data/images/cgogn2.png b/data/images/cgogn2.png new file mode 100644 index 00000000..14a75fb8 Binary files /dev/null and b/data/images/cgogn2.png differ diff --git a/data/images/igg.png b/data/images/igg.png new file mode 100644 index 00000000..616e1e8c Binary files /dev/null and b/data/images/igg.png differ diff --git a/data/meshes/off/socket.off b/data/meshes/off/socket.off new file mode 100644 index 00000000..2de151a0 --- /dev/null +++ b/data/meshes/off/socket.off @@ -0,0 +1,2534 @@ +OFF +836 1696 0 +-82.071068 7.071068 25 +-75 10 25 +-67.928932 7.071068 25 +-65 0 25 +-67.928932 -7.071068 25 +-75 -10 25 +-82.071068 -7.071068 25 +-85 0 25 +-82.071068 -7.071068 -25 +-75 -10 -25 +-67.928932 -7.071068 -25 +-65 0 -25 +-67.928932 7.071068 -25 +-75 10 -25 +-82.071068 7.071068 -25 +-85 0 -25 +67.928932 -7.071068 -25 +75 -10 -25 +82.071068 -7.071068 -25 +85 0 -25 +82.071068 7.071068 -25 +75 10 -25 +67.928932 7.071068 -25 +65 0 -25 +67.928932 7.071068 25 +75 10 25 +82.071068 7.071068 25 +85 0 25 +82.071068 -7.071068 25 +75 -10 25 +67.928932 -7.071068 25 +65 0 25 +27.5 39.393398 60.606602 +27.5 50 65 +27.5 60.606602 60.606602 +27.5 35 50 +27.5 65 50 +27.5 25.495098 50 +27.5 25.495098 62.5 +27.5 25.495098 75 +27.5 78.482091 75 +27.5 60.81976 75 +27.5 43.157429 75 +27.5 96.144423 75 +27.5 96.144423 62.5 +27.5 96.144423 50 +27.5 80.572211 50 +25.016026 -96.820444 50 +22.515474 -97.432302 50 +27.5 -96.144423 50 +20 -97.97959 50 +27.5 -80.572211 50 +27.5 -65 50 +20 -65 50 +20 -81.489795 50 +27.5 -35 50 +20 -35 50 +27.5 -25.495098 50 +22.677415 -29.866115 50 +25.183719 -27.785433 50 +20 -31.721444 50 +20 35 50 +20 31.721444 50 +25.183719 27.785433 50 +22.677415 29.866115 50 +20 65 50 +22.515474 97.432302 50 +25.016026 96.820444 50 +20 97.97959 50 +20 81.489795 50 +-25.016026 96.820444 50 +-22.515474 97.432302 50 +-27.5 96.144423 50 +-20 97.97959 50 +-27.5 78.072211 50 +-27.5 60 50 +-20 60 50 +-20 78.989795 50 +-27.5 40 50 +-20 40 50 +-27.5 25.495098 50 +-22.677415 29.866115 50 +-25.183719 27.785433 50 +-20 31.721444 50 +-20 -40 50 +-27.5 -40 50 +-20 -31.721444 50 +-25.183719 -27.785433 50 +-22.677415 -29.866115 50 +-27.5 -25.495098 50 +-27.5 -60 50 +-20 -60 50 +-27.5 -78.072211 50 +-27.5 -96.144423 50 +-22.515474 -97.432302 50 +-25.016026 -96.820444 50 +-20 -97.97959 50 +-20 -78.989795 50 +-27.5 96.144423 62.5 +-27.5 96.144423 75 +-27.5 43.157429 75 +-27.5 60.81976 75 +-27.5 78.482091 75 +-27.5 25.495098 75 +-27.5 25.495098 62.5 +-27.5 57.071068 57.071068 +-27.5 50 60 +-27.5 42.928932 57.071068 +-27.5 -42.928932 57.071068 +-27.5 -50 60 +-27.5 -57.071068 57.071068 +-27.5 -25.495098 62.5 +-27.5 -25.495098 75 +-27.5 -78.482091 75 +-27.5 -60.81976 75 +-27.5 -43.157429 75 +-27.5 -96.144423 75 +-27.5 -96.144423 62.5 +27.5 -96.144423 62.5 +27.5 -96.144423 75 +27.5 -43.157429 75 +27.5 -60.81976 75 +27.5 -78.482091 75 +27.5 -25.495098 75 +27.5 -25.495098 62.5 +27.5 -60.606602 60.606602 +27.5 -50 65 +27.5 -39.393398 60.606602 +-20 -97.97959 16.666667 +-20 -97.97959 33.333333 +-20 -97.97959 0 +-20 -81.415053 0 +-20 -64.850517 0 +-20 -48.28598 0 +-20 -31.721444 0 +-20 -31.721444 16.666667 +-20 -31.721444 33.333333 +-20 -42.928932 42.928932 +-20 -50 40 +-20 -57.071068 42.928932 +50 -39.393398 60.606602 +50 -35 50 +50 -39.393398 39.393398 +50 -50 35 +50 -60.606602 39.393398 +50 -65 50 +50 -60.606602 60.606602 +50 -50 65 +20 -60.606602 39.393398 +20 -50 35 +20 -39.393398 39.393398 +20 -31.721444 33.333333 +20 -31.721444 16.666667 +20 -31.721444 0 +20 -48.28598 0 +20 -64.850517 0 +20 -81.415053 0 +20 -97.97959 0 +20 -97.97959 33.333333 +20 -97.97959 16.666667 +20 97.97959 16.666667 +20 97.97959 33.333333 +20 97.97959 0 +20 81.415053 0 +20 64.850517 0 +20 48.28598 0 +20 31.721444 0 +20 31.721444 16.666667 +20 31.721444 33.333333 +20 39.393398 39.393398 +20 50 35 +20 60.606602 39.393398 +-50 86.60254 -58.333333 +-50 86.60254 -41.666667 +-50 86.60254 -75 +-50 86.60254 -25 +-64.278761 76.604444 -25 +-76.604444 64.278761 -25 +-86.60254 50 -25 +-93.969262 34.202014 -25 +-98.480775 17.364818 -25 +-100 0 -25 +-98.480775 -17.364818 -25 +-93.969262 -34.202014 -25 +-86.60254 -50 -25 +-76.604444 -64.278761 -25 +-64.278761 -76.604444 -25 +-50 -86.60254 -25 +-50 -86.60254 -41.666667 +-50 -86.60254 -58.333333 +-50 -86.60254 -75 +34.202014 -93.969262 -75 +17.364818 -98.480775 -75 +0 -100 -75 +-17.364818 -98.480775 -75 +-34.202014 -93.969262 -75 +50 -86.60254 -75 +50 -86.60254 -58.333333 +50 -86.60254 -41.666667 +50 -86.60254 -25 +64.278761 -76.604444 -25 +76.604444 -64.278761 -25 +86.60254 -50 -25 +93.969262 -34.202014 -25 +98.480775 -17.364818 -25 +100 0 -25 +98.480775 17.364818 -25 +93.969262 34.202014 -25 +86.60254 50 -25 +76.604444 64.278761 -25 +64.278761 76.604444 -25 +50 86.60254 -25 +50 86.60254 -41.666667 +50 86.60254 -58.333333 +50 86.60254 -75 +-34.202014 93.969262 -75 +-17.364818 98.480775 -75 +0 100 -75 +17.364818 98.480775 -75 +34.202014 93.969262 -75 +-42.768401 -90.392831 75 +-35.251699 -93.580541 75 +-50 -86.60254 75 +-50 -86.60254 58.333333 +-50 -86.60254 41.666667 +-50 -86.60254 25 +-64.278761 -76.604444 25 +-76.604444 -64.278761 25 +-86.60254 -50 25 +-93.969262 -34.202014 25 +-98.480775 -17.364818 25 +-100 0 25 +-98.480775 17.364818 25 +-93.969262 34.202014 25 +-86.60254 50 25 +-76.604444 64.278761 25 +-64.278761 76.604444 25 +-50 86.60254 25 +-50 86.60254 41.666667 +-50 86.60254 58.333333 +-50 86.60254 75 +-35.251699 93.580541 75 +-42.768401 90.392831 75 +-20 97.97959 33.333333 +-20 97.97959 16.666667 +-20 97.97959 0 +-13.383581 99.100352 0 +-6.706892 99.774834 0 +0 100 0 +6.706892 99.774834 0 +13.383581 99.100352 0 +42.768401 90.392831 75 +35.251699 93.580541 75 +50 86.60254 75 +50 86.60254 58.333333 +50 86.60254 41.666667 +50 86.60254 25 +64.278761 76.604444 25 +76.604444 64.278761 25 +86.60254 50 25 +93.969262 34.202014 25 +98.480775 17.364818 25 +100 0 25 +98.480775 -17.364818 25 +93.969262 -34.202014 25 +86.60254 -50 25 +76.604444 -64.278761 25 +64.278761 -76.604444 25 +50 -86.60254 25 +50 -86.60254 41.666667 +50 -86.60254 58.333333 +50 -86.60254 75 +35.251699 -93.580541 75 +42.768401 -90.392831 75 +13.383581 -99.100352 0 +6.706892 -99.774834 0 +0 -100 0 +-6.706892 -99.774834 0 +-13.383581 -99.100352 0 +-50 42.928932 57.071068 +-50 40 50 +-50 42.928932 42.928932 +-50 50 40 +-50 57.071068 42.928932 +-50 60 50 +-50 57.071068 57.071068 +-50 50 60 +-20 57.071068 42.928932 +-20 50 40 +-20 42.928932 42.928932 +-36.341675 -9.248389 75 +-36.341675 9.248389 75 +-50 67.357531 75 +-50 48.112522 75 +-50 28.867513 75 +-50 9.622504 75 +-50 -9.622504 75 +-50 -28.867513 75 +-50 -48.112522 75 +-50 -67.357531 75 +-32.475953 -18.75 -75 +-18.75 -32.475953 -75 +0 -37.5 -75 +18.75 -32.475953 -75 +32.475953 -18.75 -75 +37.5 0 -75 +32.475953 18.75 -75 +18.75 32.475953 -75 +0 37.5 -75 +-18.75 32.475953 -75 +-32.475953 18.75 -75 +-37.5 0 -75 +6.990569 -36.842665 0 +-6.990569 -36.842665 0 +36.341675 9.248389 75 +36.341675 -9.248389 75 +-6.990569 36.842665 0 +6.990569 36.842665 0 +-20 31.721444 0 +-20 31.721444 33.333333 +-20 31.721444 16.666667 +-20 48.28598 0 +-20 64.850517 0 +-20 81.415053 0 +-50 -57.071068 57.071068 +-50 -60 50 +-50 -57.071068 42.928932 +-50 -50 40 +-50 -42.928932 42.928932 +-50 -40 50 +-50 -42.928932 57.071068 +-50 -50 60 +50 60.606602 60.606602 +50 65 50 +50 60.606602 39.393398 +50 50 35 +50 39.393398 39.393398 +50 35 50 +50 39.393398 60.606602 +50 50 65 +50 -67.357531 75 +50 -48.112522 75 +50 -28.867513 75 +50 -9.622504 75 +50 9.622504 75 +50 28.867513 75 +50 48.112522 75 +50 67.357531 75 +-50 67.357531 25 +-50 48.112522 25 +-50 28.867513 25 +-50 9.622504 25 +-50 -9.622504 25 +-50 -28.867513 25 +-50 -48.112522 25 +-50 -67.357531 25 +-50 -67.357531 -25 +-50 -48.112522 -25 +-50 -28.867513 -25 +-50 -9.622504 -25 +-50 9.622504 -25 +-50 28.867513 -25 +-50 48.112522 -25 +-50 67.357531 -25 +-50 -67.357531 -75 +-50 -48.112522 -75 +-50 -28.867513 -75 +-50 -9.622504 -75 +-50 9.622504 -75 +-50 28.867513 -75 +-50 48.112522 -75 +-50 67.357531 -75 +50 67.357531 -25 +50 48.112522 -25 +50 28.867513 -25 +50 9.622504 -25 +50 -9.622504 -25 +50 -28.867513 -25 +50 -48.112522 -25 +50 -67.357531 -25 +50 67.357531 -75 +50 48.112522 -75 +50 28.867513 -75 +50 9.622504 -75 +50 -9.622504 -75 +50 -28.867513 -75 +50 -48.112522 -75 +50 -67.357531 -75 +50 -67.357531 25 +50 -48.112522 25 +50 -28.867513 25 +50 -9.622504 25 +50 9.622504 25 +50 28.867513 25 +50 48.112522 25 +50 67.357531 25 +-85 0 8.333333 +-85 0 -8.333333 +-82.071068 -7.071068 8.333333 +-82.071068 -7.071068 -8.333333 +-75 -10 8.333333 +-75 -10 -8.333333 +-67.928932 -7.071068 8.333333 +-67.928932 -7.071068 -8.333333 +-65 0 8.333333 +-65 0 -8.333333 +-67.928932 7.071068 8.333333 +-67.928932 7.071068 -8.333333 +-75 10 8.333333 +-75 10 -8.333333 +-82.071068 7.071068 8.333333 +-82.071068 7.071068 -8.333333 +65 0 -8.333333 +65 0 8.333333 +67.928932 7.071068 -8.333333 +67.928932 7.071068 8.333333 +75 10 -8.333333 +75 10 8.333333 +82.071068 7.071068 -8.333333 +82.071068 7.071068 8.333333 +85 0 -8.333333 +85 0 8.333333 +82.071068 -7.071068 -8.333333 +82.071068 -7.071068 8.333333 +75 -10 -8.333333 +75 -10 8.333333 +67.928932 -7.071068 -8.333333 +67.928932 -7.071068 8.333333 +27.5 66.217131 67.750352 +27.5 76.800411 61.111562 +27.5 36.173296 68.114492 +-27.5 73.455304 63.511719 +-27.5 55.247625 66.911641 +-27.5 38.838351 66.792537 +-27.5 -73.455307 63.511719 +-27.5 -55.247627 66.911641 +-27.5 -38.838352 66.792537 +27.5 -76.800407 61.111564 +27.5 -66.217132 67.750352 +27.5 -36.173296 68.114492 +-20 -78.849458 31.600615 +-20 -75.682924 15.122891 +-20 -57.676405 13.425665 +-20 -62.172491 27.28862 +-20 -43.085913 11.29981 +-20 -45.698164 25.788478 +38.741861 -44.338541 63.890568 +38.741076 -55.909211 63.786995 +38.618455 -63.970997 55.459966 +36.695633 -63.566697 43.601193 +35.089886 -55.57227 36.073414 +35.092946 -44.363931 36.099111 +36.71462 -36.392314 43.688829 +38.626963 -36.085053 55.601272 +20 -69.450639 14.8283 +20 -49.85168 11.8026 +20 -76.06184 33.425002 +20 -84.376106 19.604105 +20 -59.585169 25.516816 +20 -43.758042 25.253076 +20 79.223331 32.182878 +20 76.022241 15.003858 +20 57.807763 12.768537 +20 62.892879 25.760185 +20 42.989068 10.709787 +20 45.506412 24.021148 +-99.588102 -9.066974 -12.37865 +-99.99917 0.407363 -0.064789 +-99.534041 9.642336 12.258466 +-96.220251 -27.233495 12.312195 +-96.131018 -27.546823 -12.384888 +-89.467987 -44.670788 12.234547 +-88.888615 -45.812815 -12.410965 +-79.366412 -60.835619 12.662753 +-76.660997 -64.211303 -12.920679 +-65.779748 -75.319484 14.951772 +-61.273865 -79.028561 -10.042285 +-30.514977 -95.230437 -54.008694 +60.489433 -79.630575 11.943392 +76.129935 -64.840057 13.177491 +86.82455 -49.613481 -13.429059 +88.410498 -46.728834 12.115367 +95.906673 -28.318017 12.08509 +95.646989 -29.183103 -12.516497 +96.217368 27.243679 12.311479 +96.118467 27.590583 -12.382087 +89.462467 44.681841 12.23681 +88.878664 45.832119 -12.40963 +79.360693 60.84308 12.664449 +76.654351 64.219238 -12.920504 +65.776121 75.322652 14.952959 +61.270104 79.031477 -10.042045 +30.538612 95.222861 -54.016733 +-60.486018 79.633169 11.927551 +-76.119311 64.852528 13.168349 +-86.806095 49.645763 -13.444667 +-88.391782 46.764226 12.106594 +-95.887225 28.3838 12.074761 +-95.626336 29.250706 -12.536873 +-56.954731 82.195855 -12.887738 +-49.976728 86.615972 -1.380875 +-46.179621 88.698606 12.217146 +-39.266805 91.968027 55.9654 +-36.97821 92.91185 37.516958 +-34.329305 93.922834 21.874578 +-34.285048 93.938999 4.174003 +-34.65456 93.803313 -16.147645 +-36.1727 93.228407 -36.968057 +-38.83429 92.151495 -54.281914 +-73.44845 67.862546 -12.404335 +-67.420829 73.854125 -0.150617 +-81.628924 57.764338 -0.210629 +-91.927776 39.360944 -0.583074 +-99.509557 9.891814 -12.409083 +-98.004023 19.879927 -0.222364 +-98.265578 -18.543899 -0.056713 +-99.600156 -8.933579 12.32773 +-92.881588 -37.054159 -0.137898 +-83.552693 -54.944949 -0.206588 +-70.34697 -71.072525 1.473909 +-47.47897 -88.009928 -7.633407 +-53.010926 -84.792934 7.178593 +-34.079898 -94.013619 -33.053263 +-34.771644 -93.759974 -13.962524 +-35.613341 -93.443512 4.120261 +-36.322964 -93.169965 20.306846 +-37.053042 -92.882033 37.170318 +-39.265605 -91.96854 55.874366 +-9.632927 -99.534952 -55.73518 +-16.406878 -98.64489 -37.15157 +-20.657332 -97.843112 -19.043954 +9.041645 -99.590404 -55.664859 +2.171108 -99.976429 -37.079309 +-4.152573 -99.913743 -18.407322 +25.491126 -96.696445 -55.80908 +20.511781 -97.873729 -36.100101 +14.137788 -98.99557 -18.629246 +38.850587 -92.144625 -54.264019 +36.214097 -93.212334 -36.931122 +34.732691 -93.774411 -16.093226 +34.332137 -93.921799 4.182495 +34.339585 -93.919076 21.868572 +36.977458 -92.91215 37.515326 +39.266534 -91.968143 55.963581 +56.965449 -82.188427 -12.869198 +49.987393 -86.609818 -1.359143 +46.178136 -88.699378 12.225064 +73.461135 -67.848815 -12.39039 +67.434335 -73.841794 -0.134955 +81.651934 -57.731809 -0.197758 +91.957381 -39.29173 -0.568089 +99.518503 -9.80141 -12.386752 +98.026802 -19.767298 -0.202037 +99.590683 9.038581 -12.378887 +99.999133 -0.416489 -0.064092 +99.532933 -9.653769 12.256975 +98.264009 18.552211 -0.061308 +99.600124 8.933945 12.325478 +92.874656 37.07153 -0.1349 +83.544668 54.95715 -0.204582 +70.340865 71.078567 1.47508 +47.479791 88.009485 -7.631123 +53.008234 84.794617 7.180181 +34.102069 94.005579 -33.055721 +34.781149 93.756449 -13.959573 +35.613213 93.443561 4.122136 +36.322183 93.170269 20.308034 +37.053025 92.88204 37.170639 +39.265609 91.968538 55.874454 +9.680827 99.530305 -55.760534 +16.459619 98.636104 -37.169662 +20.688114 97.836608 -19.048854 +-8.984267 99.595597 -55.71053 +-2.088058 99.978198 -37.124467 +4.205481 99.911531 -18.422235 +-25.451589 96.706859 -55.847768 +-20.419386 97.893047 -36.170679 +-14.053547 99.007564 -18.667904 +-38.698254 53.20965 59.47091 +-36.95309 58.253255 55.646572 +-40.103806 59.927272 51.203854 +-36.256693 58.138589 44.189375 +-35.049932 49.841053 40.001263 +-36.418407 41.520584 44.699103 +-38.574842 40.561108 53.302622 +-38.73643 45.862416 59.103867 +-40.378877 -22.153266 75 +-38.774822 25.577784 75 +-38.858315 -55.540469 75 +-38.626772 -74.36942 75 +-38.925839 -37.703161 75 +-40.558978 40.508314 75 +-38.916904 56.275321 75 +-38.627455 74.567477 75 +-37.496377 0.521254 -50.786732 +-37.34612 3.393719 -31.605883 +-37.471668 -1.457424 -15.908264 +-37.432274 -2.252751 2.366579 +-37.461065 -1.708392 21.162604 +-37.442825 -2.069993 39.250135 +-37.356059 -3.282504 58.070474 +7.008601 -36.839239 -18.239807 +-8.64115 36.490828 -17.83406 +-33.231248 17.376252 -55.970777 +-33.222771 17.392454 -36.522995 +-33.155576 17.520211 -16.560318 +-33.388811 17.071534 0.780048 +-33.472299 16.907252 18.247234 +-34.23691 15.299803 35.389781 +-35.613946 11.74295 53.860432 +-20.214231 31.585358 -56.331305 +-21.823444 30.495693 -38.013518 +-24.241989 28.610767 -21.048178 +-1.454267 37.471791 -55.704098 +-4.282418 37.254676 -37.028745 +19.866834 31.805014 -57.329315 +16.108681 33.863851 -36.789779 +11.064886 35.83041 -18.83671 +34.965536 13.552169 -56.226976 +31.579778 20.222947 -36.93665 +29.482797 23.173577 -15.338569 +32.111677 19.367245 7.48614 +32.466912 18.765651 26.288333 +33.394518 17.060368 43.40343 +33.537753 16.777042 61.051914 +36.644084 -7.96625 -56.816037 +37.499603 -0.172499 -37.903376 +37.333147 3.533568 -18.43697 +37.356911 3.272802 1.156352 +37.448284 1.968759 20.688998 +37.44021 2.116763 39.068443 +37.355894 3.284384 58.010209 +26.828068 -26.201236 -56.932431 +32.035831 -19.492448 -39.230437 +33.696724 -16.455418 -19.502895 +33.783859 -16.275775 -0.75261 +33.650314 -16.550117 17.521941 +34.273953 -15.21664 35.087941 +35.619417 -11.726343 53.745338 +9.489697 -36.279411 -56.410811 +17.313167 -33.264158 -38.666599 +23.266901 -29.409204 -22.288117 +-9.770743 -36.204732 -55.344424 +-1.828399 -37.4554 -36.940814 +-25.089759 -27.870306 -52.715364 +-21.223012 -30.916561 -34.873957 +-13.47025 -34.997176 -18.341102 +-33.744642 -16.356929 -59.879757 +-34.329593 -15.090694 -36.407333 +-30.972298 -21.141589 -14.419034 +-32.339441 -18.984481 7.84387 +-32.49864 -18.710649 26.424259 +-33.396742 -17.056014 43.463962 +-33.535093 -16.782357 61.074505 +-20 49.715169 12.440509 +-20 74.551916 34.028042 +-20 68.907302 15.370747 +-20 83.967391 19.922929 +-20 58.672175 27.261162 +-20 43.921125 27.018902 +-40.508442 -48.156945 59.82869 +-36.609348 -58.891473 45.423789 +-38.608767 -59.391142 53.436052 +-35.145621 -52.737099 40.381877 +-35.886189 -43.420631 42.46927 +-38.402067 -40.176614 51.87112 +-37.01984 -43.886884 57.9139 +-38.790254 -54.447526 58.956535 +38.74823 50.197146 64.998704 +35.184692 56.448586 36.456893 +36.854674 63.896042 44.351991 +37.13504 46.72592 35.361681 +32.364692 39.593234 39.197258 +39.560083 35.369259 46.692217 +38.772985 37.256728 57.912586 +38.660464 63.14276 57.229651 +0 -71.762166 0 +0 -54.245057 0 +0 -87.083244 0 +0 60.529325 0 +0 47.412013 0 +0 80.014946 0 +38.774821 25.577765 75 +40.558978 40.508299 75 +40.378877 -22.153267 75 +38.925839 -37.703162 75 +38.858316 -55.540192 75 +38.626773 -74.369344 75 +38.916904 56.275314 75 +38.627455 74.567475 75 +-77.423255 -43.447196 25 +-86.33483 -19.81352 25 +-67.588595 27.012803 25 +-90.471966 14.663408 25 +-81.203046 24.558943 25 +-58.929137 18.106565 25 +-62.926464 -20.662915 25 +-91.367901 -8.97974 25 +-61.448249 60.172793 25 +-77.788453 41.295218 25 +-64.125395 44.51691 25 +-76.540295 -27.942658 25 +-63.201222 -36.507591 25 +-65.912904 -50.642526 25 +-61.275259 -61.62573 25 +-50 38.193136 66.569022 +-50 -59.399099 66.755393 +-50 -72.401553 61.537404 +-50 -72.739848 45.131461 +-50 -24.343061 54.649602 +-50 -24.314092 38.912274 +-50 72.761495 54.96944 +-50 72.904307 38.704775 +-50 24.776998 61.290433 +-50 24.424955 45.436886 +-50 9.316713 41.875475 +-50 7.72654 59.534878 +-50 -7.540858 40.511457 +-50 -9.207252 58.159575 +-87.135149 -19.220918 -25 +-67.167247 -27.287265 -25 +-89.720675 15.452705 -25 +-77.68985 42.731878 -25 +-78.127696 25.782915 -25 +-79.813828 -27.123281 -25 +-58.840874 -18.134609 -25 +-63.172059 20.405988 -25 +-63.769996 35.895242 -25 +-66.078243 50.334594 -25 +-61.317686 61.526283 -25 +-63.953949 -44.700382 -25 +-77.479371 -42.109533 -25 +-61.418042 -60.242342 -25 +-91.516833 -8.740109 -25 +-50 66.604179 -60.966269 +-50 72.44084 -45.17814 +-50 48.928629 -56.135798 +-50 56.970803 -41.652229 +-50 32.791901 -58.134247 +-50 38.914054 -40.855341 +-50 14.093543 -58.356577 +-50 20.622669 -41.552551 +-50 -6.163981 -58.602686 +-50 1.317746 -41.877236 +-50 -29.041455 -59.965488 +-50 -18.938835 -42.487796 +-50 -51.763139 -58.125934 +-50 -39.60672 -42.304491 +-50 -70.304863 -55.128859 +-50 -61.077499 -40.899625 +77.423242 -43.447238 -25 +86.334807 -19.81355 -25 +67.585436 27.015222 -25 +62.926458 -20.662942 -25 +58.9285 18.106865 -25 +91.367895 -8.97975 -25 +90.470518 14.665174 -25 +81.201508 24.559765 -25 +76.540278 -27.942689 -25 +63.201215 -36.507621 -25 +65.912896 -50.642546 -25 +61.275256 -61.625736 -25 +64.123203 44.519044 -25 +77.788195 41.295283 -25 +61.448385 60.172046 -25 +50 -61.118246 -59.088633 +50 -70.262787 -44.856084 +50 -39.669684 -57.69078 +50 -51.517671 -41.871959 +50 -19.333378 -57.760889 +50 -28.012495 -40.217643 +50 -1.760258 -61.230518 +50 -2.829307 -43.248436 +50 14.866307 -58.441649 +50 19.888272 -41.793379 +50 33.981043 -58.287178 +50 39.958592 -41.628322 +50 52.870628 -58.381629 +50 58.501409 -41.559406 +50 70.779 -58.528654 +50 74.959867 -41.294684 +87.11385 -19.277172 25 +60.991019 -18.016721 25 +89.730314 15.447173 25 +77.699605 42.739796 25 +63.183491 20.410589 25 +78.140218 25.786524 25 +63.776361 35.899825 25 +67.391076 -29.045332 25 +79.857995 -27.447779 25 +61.391488 -60.385797 25 +77.614598 -42.546229 25 +63.944394 -45.213285 25 +91.510226 -8.757084 25 +66.08118 50.336823 25 +61.317848 61.526518 25 +50 -75.17519 35.267595 +50 74.290594 44.820281 +50 74.341466 61.858187 +50 28.238796 40.55966 +50 22.593933 54.227214 +50 17.758905 37.346645 +50 -75.406119 48.016599 +50 -74.333361 62.56713 +50 -23.053208 44.896639 +50 -22.224479 61.243058 +50 -12.372181 39.013425 +50 -5.589706 57.554146 +50 4.243663 42.615794 +50 11.803688 60.857216 +-36.731633 -34.203621 -75 +-8.178436 -47.014752 -75 +-20.343055 -50.168629 -75 +30.187853 -43.32571 -75 +8.349635 -49.048221 -75 +-10.249794 -63.560712 -75 +-32.230785 -45.34742 -75 +-29.949995 43.173224 -75 +-6.732626 49.196756 -75 +14.818236 47.934131 -75 +33.560835 39.249145 -75 +-27.838252 -78.246084 -75 +-4.713146 -80.840511 -75 +16.765401 -81.856419 -75 +35.873494 -78.265842 -75 +-32.335892 -60.598238 -75 +12.118959 -63.910368 -75 +31.936616 -62.744907 -75 +-32.838404 61.915828 -75 +-12.961216 63.576348 -75 +9.377273 64.348873 -75 +31.034098 58.403077 -75 +-37.07993 77.759669 -75 +-20.405158 79.727836 -75 +1.4079 82.267076 -75 +26.887872 77.989134 -75 +3 6 398 7 +3 6 400 398 +3 6 5 400 +3 400 5 402 +3 403 402 405 +3 11 405 12 +3 11 403 405 +3 11 10 403 +3 403 10 401 +3 400 401 398 +3 400 403 401 +3 400 402 403 +3 5 4 402 +3 402 4 404 +3 405 404 407 +3 12 407 13 +3 12 405 407 +3 4 3 404 +3 404 3 406 +3 407 406 409 +3 13 409 14 +3 13 407 409 +3 3 2 406 +3 406 2 408 +3 409 408 411 +3 14 411 15 +3 14 409 411 +3 2 1 408 +3 408 1 410 +3 411 410 397 +3 15 397 8 +3 15 411 397 +3 1 0 410 +3 410 0 396 +3 397 396 399 +3 8 399 9 +3 8 397 399 +3 0 7 396 +3 396 7 398 +3 399 398 401 +3 9 401 10 +3 9 399 401 +3 396 397 410 +3 399 396 398 +3 405 402 404 +3 407 404 406 +3 409 406 408 +3 411 408 410 +3 22 414 23 +3 22 416 414 +3 22 21 416 +3 416 21 418 +3 419 418 421 +3 27 421 28 +3 27 419 421 +3 27 26 419 +3 419 26 417 +3 416 417 414 +3 416 419 417 +3 416 418 419 +3 21 20 418 +3 418 20 420 +3 421 420 423 +3 28 423 29 +3 28 421 423 +3 20 19 420 +3 420 19 422 +3 423 422 425 +3 29 425 30 +3 29 423 425 +3 19 18 422 +3 422 18 424 +3 425 424 427 +3 30 427 31 +3 30 425 427 +3 18 17 424 +3 424 17 426 +3 427 426 413 +3 31 413 24 +3 31 427 413 +3 17 16 426 +3 426 16 412 +3 413 412 415 +3 24 415 25 +3 24 413 415 +3 16 23 412 +3 412 23 414 +3 415 414 417 +3 25 417 26 +3 25 415 417 +3 412 413 426 +3 415 412 414 +3 421 418 420 +3 423 420 422 +3 425 422 424 +3 427 424 426 +3 46 36 429 +3 44 429 40 +3 43 44 40 +3 33 428 34 +3 33 41 428 +3 33 42 41 +3 33 430 42 +3 33 32 430 +3 430 32 38 +3 39 430 38 +3 39 42 430 +3 32 35 38 +3 38 35 37 +3 41 40 428 +3 428 40 429 +3 34 429 36 +3 34 428 429 +3 45 46 44 +3 44 46 429 +3 50 48 54 +3 54 48 47 +3 51 47 49 +3 51 54 47 +3 51 53 54 +3 51 52 53 +3 60 56 58 +3 58 56 55 +3 59 55 57 +3 59 58 55 +3 61 64 35 +3 61 62 64 +3 64 63 35 +3 35 63 37 +3 36 46 65 +3 65 46 69 +3 69 46 67 +3 66 69 67 +3 66 68 69 +3 46 45 67 +3 73 71 77 +3 77 71 70 +3 74 70 72 +3 74 77 70 +3 74 76 77 +3 74 75 76 +3 83 79 81 +3 81 79 78 +3 82 78 80 +3 82 81 78 +3 84 88 85 +3 84 86 88 +3 88 87 85 +3 85 87 89 +3 90 92 91 +3 91 92 97 +3 97 92 95 +3 94 97 95 +3 94 96 97 +3 92 93 95 +3 72 98 74 +3 74 98 431 +3 105 431 432 +3 106 432 433 +3 107 433 104 +3 80 107 104 +3 80 78 107 +3 99 102 98 +3 98 102 431 +3 431 102 101 +3 432 101 100 +3 433 100 103 +3 104 433 103 +3 431 101 432 +3 432 100 433 +3 107 106 433 +3 106 105 432 +3 75 74 105 +3 105 74 431 +3 90 110 92 +3 92 110 434 +3 117 434 113 +3 116 117 113 +3 434 110 435 +3 114 435 115 +3 114 434 435 +3 114 113 434 +3 108 436 109 +3 108 111 436 +3 108 89 111 +3 108 85 89 +3 111 112 436 +3 436 112 115 +3 435 436 115 +3 435 109 436 +3 435 110 109 +3 93 92 117 +3 117 92 434 +3 49 118 51 +3 51 118 437 +3 52 437 125 +3 52 51 437 +3 119 122 118 +3 118 122 437 +3 437 122 438 +3 125 438 126 +3 125 437 438 +3 122 121 438 +3 438 121 126 +3 126 121 120 +3 439 120 123 +3 124 439 123 +3 124 127 439 +3 124 55 127 +3 124 57 55 +3 126 120 439 +3 127 126 439 +3 91 97 139 +3 139 97 440 +3 443 440 441 +3 442 441 132 +3 133 442 132 +3 133 444 442 +3 133 134 444 +3 444 134 135 +3 445 135 136 +3 137 136 86 +3 84 137 86 +3 96 129 97 +3 97 129 440 +3 440 129 128 +3 441 128 131 +3 132 441 131 +3 128 130 131 +3 444 135 445 +3 442 445 443 +3 441 442 443 +3 445 136 137 +3 138 445 137 +3 138 443 445 +3 138 139 443 +3 443 139 440 +3 128 441 440 +3 444 445 442 +3 146 447 147 +3 146 448 447 +3 146 145 448 +3 448 145 449 +3 52 449 148 +3 53 52 148 +3 145 144 449 +3 449 144 450 +3 148 450 149 +3 148 449 450 +3 144 143 450 +3 450 143 451 +3 149 451 150 +3 149 450 451 +3 143 142 451 +3 451 142 452 +3 150 452 55 +3 56 150 55 +3 142 141 452 +3 452 141 453 +3 55 453 127 +3 55 452 453 +3 141 140 453 +3 453 140 446 +3 127 446 126 +3 127 453 446 +3 140 147 446 +3 446 147 447 +3 126 447 125 +3 126 446 447 +3 449 52 448 +3 448 52 125 +3 447 448 125 +3 452 150 451 +3 50 54 158 +3 158 54 456 +3 457 456 454 +3 156 454 155 +3 156 457 454 +3 156 159 457 +3 156 157 159 +3 54 53 456 +3 456 53 148 +3 458 148 149 +3 459 149 150 +3 151 150 60 +3 151 459 150 +3 151 152 459 +3 459 152 455 +3 458 455 454 +3 456 458 454 +3 456 148 458 +3 458 149 459 +3 455 458 459 +3 150 56 60 +3 152 153 455 +3 455 153 154 +3 155 455 154 +3 155 454 455 +3 159 158 457 +3 457 158 456 +3 171 65 460 +3 463 460 461 +3 462 461 164 +3 165 462 164 +3 165 464 462 +3 165 166 464 +3 464 166 167 +3 465 167 168 +3 169 168 62 +3 61 169 62 +3 68 161 69 +3 69 161 460 +3 65 69 460 +3 161 160 460 +3 460 160 461 +3 461 160 163 +3 164 461 163 +3 160 162 163 +3 464 167 465 +3 462 465 463 +3 461 462 463 +3 465 168 169 +3 170 465 169 +3 170 463 465 +3 170 171 463 +3 463 171 460 +3 464 465 462 +3 174 172 215 +3 215 172 508 +3 575 508 507 +3 576 507 506 +3 577 506 245 +3 246 577 245 +3 246 247 577 +3 577 247 574 +3 573 574 570 +3 569 570 492 +3 218 492 219 +3 218 569 492 +3 218 217 569 +3 569 217 572 +3 573 572 576 +3 577 576 506 +3 577 573 576 +3 577 574 573 +3 172 173 508 +3 508 173 507 +3 507 173 175 +3 506 175 499 +3 500 499 510 +3 493 510 494 +3 236 494 235 +3 236 493 494 +3 236 237 493 +3 493 237 501 +3 500 501 505 +3 506 505 245 +3 506 500 505 +3 506 499 500 +3 175 176 499 +3 499 176 509 +3 510 509 511 +3 494 511 496 +3 234 496 233 +3 234 494 496 +3 234 235 494 +3 176 177 509 +3 509 177 495 +3 511 495 512 +3 496 512 497 +3 233 497 232 +3 233 496 497 +3 177 178 495 +3 495 178 179 +3 498 179 180 +3 513 180 181 +3 466 181 182 +3 470 182 183 +3 472 183 184 +3 474 184 185 +3 186 474 185 +3 186 476 474 +3 186 187 476 +3 476 187 520 +3 521 520 524 +3 525 524 128 +3 129 525 128 +3 129 526 525 +3 129 93 526 +3 129 95 93 +3 129 94 95 +3 129 96 94 +3 495 179 498 +3 512 498 514 +3 497 514 468 +3 232 468 231 +3 232 497 468 +3 498 180 513 +3 514 513 467 +3 468 467 516 +3 231 516 230 +3 231 468 516 +3 513 181 466 +3 467 466 515 +3 516 515 469 +3 230 469 229 +3 230 516 469 +3 466 182 470 +3 515 470 517 +3 469 517 471 +3 229 471 228 +3 229 469 471 +3 470 183 472 +3 517 472 518 +3 471 518 473 +3 228 473 227 +3 228 471 473 +3 472 184 474 +3 518 474 519 +3 473 519 475 +3 227 475 226 +3 227 473 475 +3 188 522 187 +3 188 477 522 +3 188 189 477 +3 477 189 195 +3 194 477 195 +3 194 528 477 +3 194 193 528 +3 528 193 531 +3 532 531 535 +3 536 535 539 +3 157 539 540 +3 159 540 541 +3 158 541 542 +3 49 542 543 +3 118 543 272 +3 119 118 272 +3 189 190 195 +3 193 192 531 +3 531 192 534 +3 535 534 538 +3 539 538 199 +3 544 199 200 +3 547 200 201 +3 480 201 202 +3 203 480 202 +3 203 483 480 +3 203 204 483 +3 483 204 551 +3 552 551 554 +3 555 554 557 +3 262 557 261 +3 262 555 557 +3 262 263 555 +3 555 263 482 +3 552 482 550 +3 483 550 480 +3 483 552 550 +3 483 551 552 +3 192 191 534 +3 534 191 537 +3 538 537 198 +3 199 538 198 +3 196 197 191 +3 191 197 537 +3 537 197 198 +3 539 199 544 +3 545 544 548 +3 478 548 479 +3 267 479 266 +3 267 478 479 +3 267 268 478 +3 478 268 546 +3 545 546 540 +3 539 545 540 +3 539 544 545 +3 544 200 547 +3 548 547 549 +3 479 549 481 +3 265 481 264 +3 265 479 481 +3 265 266 479 +3 547 201 480 +3 549 480 550 +3 481 550 482 +3 264 482 263 +3 264 481 482 +3 204 205 551 +3 551 205 553 +3 554 553 556 +3 557 556 484 +3 261 484 260 +3 261 557 484 +3 205 206 553 +3 553 206 485 +3 556 485 558 +3 484 558 486 +3 260 486 259 +3 260 484 486 +3 206 207 485 +3 485 207 487 +3 558 487 559 +3 486 559 488 +3 259 488 258 +3 259 486 488 +3 207 208 487 +3 487 208 489 +3 559 489 560 +3 488 560 490 +3 258 490 257 +3 258 488 490 +3 208 209 489 +3 489 209 210 +3 491 210 211 +3 561 211 564 +3 565 564 162 +3 160 565 162 +3 160 566 565 +3 160 161 566 +3 566 161 567 +3 256 567 255 +3 256 566 567 +3 256 562 566 +3 256 490 562 +3 256 257 490 +3 489 210 491 +3 560 491 562 +3 490 560 562 +3 564 211 563 +3 571 563 570 +3 574 571 570 +3 574 250 571 +3 574 249 250 +3 574 248 249 +3 574 247 248 +3 213 492 212 +3 213 219 492 +3 213 214 219 +3 217 216 572 +3 572 216 575 +3 576 575 507 +3 576 572 575 +3 216 215 575 +3 575 215 508 +3 526 93 527 +3 224 527 223 +3 224 526 527 +3 224 225 526 +3 526 225 525 +3 525 225 521 +3 524 525 521 +3 116 221 117 +3 117 221 527 +3 93 117 527 +3 221 220 527 +3 527 220 223 +3 223 220 222 +3 521 225 475 +3 519 521 475 +3 519 476 521 +3 519 474 476 +3 225 226 475 +3 238 503 237 +3 238 502 503 +3 238 239 502 +3 502 239 242 +3 241 502 242 +3 241 98 502 +3 241 99 98 +3 239 240 242 +3 98 72 502 +3 502 72 503 +3 503 72 243 +3 504 243 244 +3 505 244 245 +3 505 504 244 +3 505 501 504 +3 504 501 237 +3 503 504 237 +3 503 243 504 +3 72 70 243 +3 243 70 71 +3 73 243 71 +3 250 162 571 +3 571 162 564 +3 563 571 564 +3 68 66 161 +3 161 66 67 +3 45 161 67 +3 45 567 161 +3 45 568 567 +3 45 44 568 +3 568 44 252 +3 251 568 252 +3 251 254 568 +3 251 253 254 +3 44 43 252 +3 254 255 568 +3 568 255 567 +3 269 542 268 +3 269 543 542 +3 269 270 543 +3 543 270 273 +3 272 543 273 +3 270 271 273 +3 118 49 543 +3 542 49 158 +3 158 49 47 +3 48 158 47 +3 48 50 158 +3 158 159 541 +3 159 157 540 +3 539 157 536 +3 536 157 274 +3 275 536 274 +3 275 533 536 +3 275 276 533 +3 533 276 277 +3 278 533 277 +3 278 530 533 +3 278 130 530 +3 530 130 523 +3 522 523 187 +3 522 530 523 +3 522 529 530 +3 522 477 529 +3 529 477 528 +3 532 528 531 +3 532 529 528 +3 532 533 529 +3 532 536 533 +3 532 535 536 +3 523 130 524 +3 520 523 524 +3 520 187 523 +3 467 513 466 +3 467 468 514 +3 470 515 466 +3 515 516 467 +3 521 476 520 +3 554 551 553 +3 560 489 491 +3 562 491 561 +3 565 561 564 +3 565 562 561 +3 565 566 562 +3 512 495 498 +3 514 498 513 +3 493 501 500 +3 510 493 500 +3 509 510 499 +3 506 507 175 +3 495 511 509 +3 511 494 510 +3 496 511 512 +3 497 512 514 +3 472 517 470 +3 517 469 515 +3 474 518 472 +3 518 471 517 +3 473 518 519 +3 128 524 130 +3 533 530 529 +3 534 535 531 +3 537 538 534 +3 538 539 535 +3 268 542 541 +3 546 541 540 +3 546 268 541 +3 478 546 545 +3 548 478 545 +3 547 548 544 +3 480 549 547 +3 549 479 548 +3 481 549 550 +3 555 482 552 +3 554 555 552 +3 485 556 553 +3 556 557 554 +3 487 558 485 +3 558 484 556 +3 489 559 487 +3 559 486 558 +3 488 559 560 +3 211 561 491 +3 211 212 563 +3 563 212 492 +3 570 563 492 +3 573 570 569 +3 572 573 569 +3 285 578 286 +3 285 579 578 +3 285 580 579 +3 285 284 580 +3 580 284 581 +3 75 581 287 +3 76 75 287 +3 284 283 581 +3 581 283 582 +3 287 582 288 +3 287 581 582 +3 283 282 582 +3 582 282 281 +3 583 281 280 +3 584 280 279 +3 585 279 286 +3 578 585 286 +3 578 106 585 +3 578 105 106 +3 578 579 105 +3 105 579 75 +3 75 579 580 +3 581 75 580 +3 582 281 583 +3 289 583 78 +3 79 289 78 +3 583 280 584 +3 78 584 107 +3 78 583 584 +3 584 279 585 +3 107 585 106 +3 107 584 585 +3 583 289 582 +3 582 289 288 +3 116 113 221 +3 221 113 589 +3 220 589 222 +3 220 221 589 +3 113 114 589 +3 589 114 588 +3 299 588 298 +3 299 589 588 +3 299 222 589 +3 114 115 588 +3 588 115 590 +3 298 590 297 +3 298 588 590 +3 115 112 590 +3 590 112 586 +3 297 586 296 +3 297 590 586 +3 112 290 586 +3 586 290 296 +3 296 290 295 +3 295 290 291 +3 587 291 103 +3 100 587 103 +3 100 591 587 +3 100 592 591 +3 100 101 592 +3 592 101 593 +3 292 593 240 +3 292 592 593 +3 292 293 592 +3 592 293 591 +3 591 293 294 +3 587 294 295 +3 291 587 295 +3 101 102 593 +3 593 102 241 +3 242 593 241 +3 242 240 593 +3 102 99 241 +3 591 294 587 +3 310 603 311 +3 310 610 603 +3 310 309 610 +3 610 309 613 +3 614 613 616 +3 617 616 620 +3 166 620 621 +3 167 621 622 +3 168 622 623 +3 37 623 624 +3 38 624 39 +3 38 37 624 +3 309 308 613 +3 613 308 307 +3 615 307 306 +3 618 306 305 +3 625 305 304 +3 632 304 303 +3 639 303 302 +3 642 302 301 +3 644 301 647 +3 648 647 594 +3 595 594 604 +3 605 604 612 +3 318 612 602 +3 316 602 317 +3 316 318 602 +3 613 307 615 +3 616 615 619 +3 620 619 627 +3 628 627 635 +3 636 635 152 +3 151 636 152 +3 151 637 636 +3 151 57 637 +3 151 59 57 +3 151 58 59 +3 151 60 58 +3 615 306 618 +3 619 618 626 +3 627 626 634 +3 635 634 153 +3 152 635 153 +3 618 305 625 +3 626 625 633 +3 634 633 641 +3 153 641 601 +3 312 601 313 +3 312 153 601 +3 625 304 632 +3 633 632 640 +3 641 640 601 +3 641 633 640 +3 632 303 639 +3 640 639 643 +3 601 643 646 +3 313 646 134 +3 313 601 646 +3 639 302 642 +3 643 642 645 +3 646 645 649 +3 134 649 650 +3 135 650 651 +3 136 651 652 +3 89 652 653 +3 111 653 112 +3 111 89 653 +3 301 300 647 +3 647 300 311 +3 594 311 603 +3 604 603 611 +3 612 611 602 +3 612 604 611 +3 290 112 653 +3 600 653 652 +3 599 652 651 +3 598 651 650 +3 597 650 649 +3 596 649 648 +3 595 648 594 +3 595 596 648 +3 595 605 596 +3 595 604 605 +3 652 89 136 +3 136 89 87 +3 88 136 87 +3 88 86 136 +3 136 135 651 +3 135 134 650 +3 649 134 646 +3 637 57 638 +3 630 638 631 +3 623 631 624 +3 623 630 631 +3 623 622 630 +3 630 622 629 +3 637 629 636 +3 637 630 629 +3 637 638 630 +3 123 315 124 +3 124 315 638 +3 57 124 638 +3 638 315 631 +3 631 315 314 +3 624 314 39 +3 624 631 314 +3 623 37 168 +3 168 37 63 +3 64 168 63 +3 64 62 168 +3 168 167 622 +3 167 166 621 +3 620 166 617 +3 617 166 317 +3 602 617 317 +3 602 614 617 +3 602 611 614 +3 614 611 610 +3 613 614 610 +3 320 606 318 +3 320 607 606 +3 320 319 607 +3 607 319 608 +3 598 608 599 +3 651 598 599 +3 83 81 319 +3 319 81 82 +3 80 319 82 +3 80 608 319 +3 80 609 608 +3 80 104 609 +3 609 104 291 +3 600 291 290 +3 653 600 290 +3 104 103 291 +3 609 291 600 +3 599 600 652 +3 599 609 600 +3 599 608 609 +3 311 594 647 +3 604 594 603 +3 649 596 597 +3 597 596 606 +3 607 597 606 +3 607 598 597 +3 607 608 598 +3 606 596 605 +3 318 605 612 +3 318 606 605 +3 597 598 650 +3 645 642 644 +3 648 644 647 +3 648 645 644 +3 648 649 645 +3 643 639 642 +3 640 632 639 +3 634 641 153 +3 633 625 632 +3 626 618 625 +3 619 615 618 +3 616 613 615 +3 611 603 610 +3 617 614 616 +3 620 616 619 +3 627 619 626 +3 629 622 621 +3 628 621 620 +3 627 628 620 +3 629 621 628 +3 636 628 635 +3 636 629 628 +3 634 626 633 +3 635 627 634 +3 601 640 643 +3 646 643 645 +3 301 644 642 +3 73 77 243 +3 243 77 655 +3 657 655 656 +3 323 656 322 +3 323 657 656 +3 323 244 657 +3 323 245 244 +3 77 76 655 +3 655 76 287 +3 658 287 288 +3 659 288 289 +3 319 289 83 +3 319 659 289 +3 319 320 659 +3 659 320 654 +3 658 654 656 +3 655 658 656 +3 655 287 658 +3 658 288 659 +3 654 658 659 +3 289 79 83 +3 320 318 654 +3 654 318 321 +3 322 654 321 +3 322 656 654 +3 244 243 657 +3 657 243 655 +3 91 139 90 +3 90 139 661 +3 662 661 325 +3 324 662 325 +3 324 667 662 +3 324 331 667 +3 667 331 660 +3 109 660 666 +3 108 666 665 +3 85 665 664 +3 137 664 138 +3 137 85 664 +3 137 84 85 +3 661 139 663 +3 326 663 327 +3 326 661 663 +3 326 325 661 +3 85 108 665 +3 108 109 666 +3 660 109 667 +3 667 109 110 +3 662 110 90 +3 661 662 90 +3 667 110 662 +3 331 330 660 +3 660 330 666 +3 666 330 665 +3 665 330 329 +3 664 329 328 +3 327 664 328 +3 327 663 664 +3 664 663 138 +3 138 663 139 +3 665 329 664 +3 65 171 36 +3 36 171 670 +3 675 670 333 +3 332 675 333 +3 332 668 675 +3 332 339 668 +3 668 339 338 +3 674 338 337 +3 673 337 336 +3 672 336 671 +3 170 671 669 +3 171 669 670 +3 171 170 669 +3 671 170 672 +3 672 170 169 +3 35 169 61 +3 35 672 169 +3 35 673 672 +3 35 674 673 +3 35 32 674 +3 674 32 668 +3 338 674 668 +3 32 33 668 +3 668 33 34 +3 675 34 36 +3 670 675 36 +3 668 34 675 +3 674 337 673 +3 336 335 671 +3 671 335 669 +3 669 335 334 +3 670 334 333 +3 670 669 334 +3 336 672 673 +3 153 312 154 +3 154 312 677 +3 155 677 676 +3 156 676 678 +3 274 678 275 +3 274 156 678 +3 274 157 156 +3 312 313 677 +3 677 313 133 +3 132 677 133 +3 132 676 677 +3 132 131 676 +3 676 131 678 +3 678 131 278 +3 277 678 278 +3 277 276 678 +3 678 276 275 +3 313 134 133 +3 131 130 278 +3 156 155 676 +3 155 154 677 +3 318 316 321 +3 321 316 680 +3 679 680 165 +3 164 679 165 +3 164 681 679 +3 164 163 681 +3 681 163 250 +3 249 681 250 +3 249 248 681 +3 681 248 247 +3 246 681 247 +3 246 323 681 +3 246 245 323 +3 316 317 680 +3 680 317 165 +3 165 317 166 +3 163 162 250 +3 323 322 681 +3 681 322 679 +3 679 322 321 +3 680 679 321 +3 120 685 123 +3 120 686 685 +3 120 121 686 +3 686 121 687 +3 340 687 271 +3 340 686 687 +3 340 341 686 +3 686 341 685 +3 685 341 342 +3 684 342 343 +3 315 343 344 +3 314 344 682 +3 39 682 42 +3 39 314 682 +3 121 122 687 +3 687 122 272 +3 273 687 272 +3 273 271 687 +3 122 119 272 +3 685 342 684 +3 123 684 315 +3 123 685 684 +3 684 343 315 +3 344 345 682 +3 682 345 683 +3 42 683 688 +3 41 688 689 +3 40 689 252 +3 43 40 252 +3 345 346 683 +3 683 346 688 +3 688 346 347 +3 689 347 253 +3 251 689 253 +3 251 252 689 +3 688 347 689 +3 40 41 689 +3 41 42 688 +3 683 42 682 +3 314 315 344 +3 0 693 7 +3 0 694 693 +3 0 1 694 +3 694 1 692 +3 699 692 700 +3 235 700 698 +3 236 698 348 +3 237 236 348 +3 1 2 692 +3 692 2 695 +3 350 695 351 +3 350 692 695 +3 350 700 692 +3 350 349 700 +3 700 349 698 +3 698 349 348 +3 695 2 351 +3 351 2 3 +3 352 3 4 +3 696 4 5 +3 701 5 691 +3 229 691 230 +3 229 701 691 +3 229 690 701 +3 229 228 690 +3 690 228 227 +3 703 227 704 +3 354 704 355 +3 354 703 704 +3 354 702 703 +3 354 353 702 +3 702 353 696 +3 701 696 5 +3 701 702 696 +3 701 690 702 +3 702 690 703 +3 703 690 227 +3 351 3 352 +3 352 4 696 +3 353 352 696 +3 5 6 691 +3 691 6 697 +3 230 697 231 +3 230 691 697 +3 6 7 697 +3 697 7 231 +3 231 7 693 +3 232 693 233 +3 232 231 693 +3 236 235 698 +3 700 235 699 +3 699 235 234 +3 233 699 234 +3 233 694 699 +3 233 693 694 +3 227 226 704 +3 704 226 355 +3 355 226 225 +3 699 694 692 +3 324 706 331 +3 324 707 706 +3 324 325 707 +3 707 325 708 +3 223 708 224 +3 223 707 708 +3 223 222 707 +3 707 222 299 +3 706 299 298 +3 331 298 330 +3 331 706 298 +3 325 326 708 +3 708 326 355 +3 224 355 225 +3 224 708 355 +3 326 327 355 +3 355 327 354 +3 354 327 328 +3 353 328 710 +3 352 710 717 +3 351 717 715 +3 350 715 714 +3 281 714 280 +3 281 350 714 +3 281 349 350 +3 281 282 349 +3 349 282 348 +3 348 282 283 +3 712 283 284 +3 711 284 285 +3 292 285 286 +3 293 286 705 +3 294 705 713 +3 295 713 716 +3 296 716 718 +3 297 718 709 +3 330 709 329 +3 330 297 709 +3 330 298 297 +3 328 329 710 +3 710 329 709 +3 717 709 718 +3 715 718 716 +3 714 716 713 +3 280 713 279 +3 280 714 713 +3 286 279 705 +3 705 279 713 +3 348 283 712 +3 237 712 238 +3 237 348 712 +3 712 284 711 +3 238 711 239 +3 238 712 711 +3 711 285 292 +3 239 292 240 +3 239 711 292 +3 350 351 715 +3 351 352 717 +3 352 353 710 +3 353 354 328 +3 707 299 706 +3 297 296 718 +3 296 295 716 +3 295 294 713 +3 294 293 705 +3 293 292 286 +3 717 710 709 +3 716 714 715 +3 718 715 717 +3 8 733 15 +3 8 719 733 +3 8 9 719 +3 719 9 724 +3 183 724 731 +3 184 731 185 +3 184 183 731 +3 724 9 720 +3 731 720 730 +3 185 730 732 +3 186 732 356 +3 187 186 356 +3 11 359 10 +3 11 360 359 +3 11 12 360 +3 360 12 726 +3 361 726 727 +3 362 727 728 +3 729 728 177 +3 176 729 177 +3 176 363 729 +3 176 175 363 +3 12 13 726 +3 726 13 723 +3 727 723 722 +3 728 722 177 +3 728 727 722 +3 13 14 723 +3 723 14 721 +3 179 721 180 +3 179 723 721 +3 179 722 723 +3 179 178 722 +3 722 178 177 +3 14 15 721 +3 721 15 181 +3 180 721 181 +3 363 362 729 +3 729 362 728 +3 362 361 727 +3 361 360 726 +3 10 359 725 +3 720 725 358 +3 730 358 357 +3 732 357 356 +3 732 730 357 +3 720 358 730 +3 186 185 732 +3 730 185 731 +3 724 183 719 +3 719 183 182 +3 733 182 181 +3 15 733 181 +3 719 182 733 +3 10 725 720 +3 9 10 720 +3 358 725 359 +3 731 724 720 +3 723 727 726 +3 175 173 363 +3 363 173 735 +3 737 735 734 +3 736 734 370 +3 738 370 369 +3 740 369 368 +3 742 368 367 +3 744 367 366 +3 365 744 366 +3 365 746 744 +3 365 364 746 +3 746 364 748 +3 749 748 188 +3 356 188 187 +3 356 749 188 +3 356 357 749 +3 749 357 747 +3 746 747 744 +3 746 749 747 +3 746 748 749 +3 173 172 735 +3 735 172 734 +3 734 172 174 +3 371 734 174 +3 371 370 734 +3 736 370 738 +3 739 738 741 +3 361 741 360 +3 361 739 741 +3 361 362 739 +3 739 362 737 +3 736 737 734 +3 736 739 737 +3 736 738 739 +3 738 369 740 +3 741 740 743 +3 360 743 359 +3 360 741 743 +3 740 368 742 +3 743 742 745 +3 359 745 358 +3 359 743 745 +3 742 367 744 +3 745 744 747 +3 358 747 357 +3 358 745 747 +3 190 189 364 +3 364 189 748 +3 748 189 188 +3 362 363 737 +3 737 363 735 +3 741 738 740 +3 743 740 742 +3 745 742 744 +3 16 376 23 +3 16 753 376 +3 16 17 753 +3 753 17 758 +3 759 758 750 +3 760 750 201 +3 761 201 200 +3 379 200 199 +3 379 761 200 +3 379 378 761 +3 761 378 760 +3 201 761 760 +3 758 17 751 +3 203 751 204 +3 203 758 751 +3 203 750 758 +3 203 202 750 +3 750 202 201 +3 19 755 18 +3 19 205 755 +3 19 756 205 +3 19 20 756 +3 756 20 757 +3 207 757 763 +3 208 763 209 +3 208 207 763 +3 20 21 757 +3 757 21 752 +3 763 752 762 +3 209 762 764 +3 210 764 372 +3 211 210 372 +3 21 22 752 +3 752 22 754 +3 374 754 375 +3 374 752 754 +3 374 762 752 +3 374 373 762 +3 762 373 764 +3 764 373 372 +3 754 22 375 +3 375 22 23 +3 376 375 23 +3 205 204 755 +3 755 204 751 +3 18 751 17 +3 18 755 751 +3 760 378 759 +3 750 760 759 +3 376 753 377 +3 377 753 759 +3 378 377 759 +3 210 209 764 +3 762 209 763 +3 757 207 756 +3 756 207 206 +3 205 756 206 +3 763 757 752 +3 758 759 753 +3 199 198 379 +3 379 198 766 +3 768 766 765 +3 767 765 386 +3 385 767 386 +3 385 769 767 +3 385 384 769 +3 769 384 771 +3 772 771 773 +3 774 773 775 +3 776 775 777 +3 778 777 779 +3 780 779 213 +3 212 780 213 +3 212 211 780 +3 780 211 372 +3 778 372 373 +3 776 373 374 +3 774 374 375 +3 772 375 376 +3 770 376 377 +3 378 770 377 +3 378 768 770 +3 378 379 768 +3 768 379 766 +3 198 197 766 +3 766 197 765 +3 765 197 387 +3 386 765 387 +3 197 196 387 +3 384 383 771 +3 771 383 773 +3 773 383 382 +3 775 382 381 +3 777 381 380 +3 779 380 214 +3 213 779 214 +3 773 382 775 +3 775 381 777 +3 777 380 779 +3 780 372 778 +3 779 780 778 +3 778 373 776 +3 777 778 776 +3 776 374 774 +3 775 776 774 +3 774 375 772 +3 773 774 772 +3 772 376 770 +3 769 770 767 +3 769 772 770 +3 769 771 772 +3 767 770 768 +3 765 767 768 +3 24 392 31 +3 24 785 392 +3 24 25 785 +3 785 25 786 +3 787 786 784 +3 794 784 258 +3 795 258 257 +3 395 257 256 +3 395 795 257 +3 395 394 795 +3 795 394 794 +3 258 795 794 +3 25 26 786 +3 786 26 783 +3 260 783 261 +3 260 786 783 +3 260 784 786 +3 260 259 784 +3 784 259 258 +3 26 27 783 +3 783 27 262 +3 261 783 262 +3 262 27 793 +3 263 793 781 +3 264 781 789 +3 791 789 788 +3 792 788 390 +3 389 792 390 +3 389 790 792 +3 389 388 790 +3 790 388 267 +3 266 790 267 +3 266 792 790 +3 266 791 792 +3 266 265 791 +3 791 265 264 +3 789 791 264 +3 29 781 28 +3 29 789 781 +3 29 788 789 +3 29 782 788 +3 29 30 782 +3 782 30 391 +3 390 782 391 +3 390 788 782 +3 30 31 391 +3 391 31 392 +3 268 267 388 +3 264 263 781 +3 263 262 793 +3 794 394 787 +3 784 794 787 +3 392 785 393 +3 393 785 787 +3 394 393 787 +3 27 28 793 +3 793 28 781 +3 786 787 785 +3 791 788 792 +3 332 347 339 +3 332 798 347 +3 332 333 798 +3 798 333 797 +3 254 797 255 +3 254 798 797 +3 254 253 798 +3 798 253 347 +3 333 334 797 +3 797 334 395 +3 255 395 256 +3 255 797 395 +3 334 335 395 +3 395 335 394 +3 394 335 336 +3 393 336 799 +3 801 799 800 +3 808 800 809 +3 807 809 344 +3 343 807 344 +3 343 805 807 +3 343 342 805 +3 805 342 140 +3 141 805 140 +3 141 804 805 +3 141 142 804 +3 804 142 390 +3 806 390 391 +3 808 391 392 +3 801 392 393 +3 799 801 393 +3 336 337 799 +3 799 337 800 +3 800 337 338 +3 345 338 346 +3 345 800 338 +3 345 809 800 +3 345 344 809 +3 338 339 346 +3 346 339 347 +3 140 341 147 +3 140 342 341 +3 390 142 389 +3 389 142 143 +3 388 143 144 +3 796 144 802 +3 269 802 270 +3 269 796 802 +3 269 268 796 +3 796 268 388 +3 144 796 388 +3 389 143 388 +3 144 145 802 +3 802 145 803 +3 270 803 271 +3 270 802 803 +3 145 146 803 +3 803 146 340 +3 271 803 340 +3 146 147 340 +3 340 147 341 +3 804 390 806 +3 807 806 808 +3 809 807 808 +3 806 391 808 +3 808 392 801 +3 800 808 801 +3 393 394 336 +3 807 805 804 +3 806 807 804 +3 300 367 311 +3 300 366 367 +3 300 810 366 +3 300 301 810 +3 810 301 816 +3 365 816 825 +3 364 825 821 +3 190 821 195 +3 190 364 821 +3 302 811 301 +3 302 814 811 +3 302 303 814 +3 814 303 813 +3 826 813 827 +3 823 827 824 +3 191 824 196 +3 191 823 824 +3 191 192 823 +3 823 192 193 +3 822 193 194 +3 821 194 195 +3 821 822 194 +3 821 815 822 +3 821 825 815 +3 815 825 812 +3 811 812 301 +3 811 815 812 +3 811 814 815 +3 815 814 826 +3 822 826 823 +3 193 822 823 +3 303 304 813 +3 813 304 385 +3 386 813 385 +3 386 827 813 +3 386 387 827 +3 827 387 824 +3 824 387 196 +3 385 304 384 +3 384 304 305 +3 383 305 306 +3 382 306 820 +3 381 820 831 +3 380 831 835 +3 214 835 219 +3 214 380 835 +3 384 305 383 +3 306 307 820 +3 820 307 819 +3 831 819 830 +3 835 830 834 +3 218 834 217 +3 218 835 834 +3 218 219 835 +3 307 308 819 +3 819 308 818 +3 830 818 829 +3 834 829 833 +3 216 833 215 +3 216 834 833 +3 216 217 834 +3 308 309 818 +3 818 309 817 +3 829 817 828 +3 833 828 832 +3 215 832 174 +3 215 833 832 +3 309 310 817 +3 817 310 369 +3 370 817 369 +3 370 828 817 +3 370 371 828 +3 828 371 832 +3 832 371 174 +3 369 310 368 +3 368 310 311 +3 367 368 311 +3 364 365 825 +3 816 365 810 +3 810 365 366 +3 380 381 831 +3 381 382 820 +3 382 383 306 +3 825 816 812 +3 812 816 301 +3 826 814 813 +3 829 818 817 +3 830 819 818 +3 831 820 819 +3 826 822 815 +3 827 823 826 +3 833 829 828 +3 834 830 829 +3 835 831 830 diff --git a/thirdparty/OffBinConverter/off_ascii2bin.cpp b/thirdparty/OffBinConverter/off_ascii2bin.cpp index ea5db530..d9ba16ba 100644 --- a/thirdparty/OffBinConverter/off_ascii2bin.cpp +++ b/thirdparty/OffBinConverter/off_ascii2bin.cpp @@ -4,8 +4,9 @@ #include #include -#include -#include +#include +#include + using namespace cgogn::numerics; int main(int argc, char **argv) diff --git a/thirdparty/TinyXml2/CMakeLists.txt b/thirdparty/TinyXml2/CMakeLists.txt index dbdd35c0..f58247ea 100644 --- a/thirdparty/TinyXml2/CMakeLists.txt +++ b/thirdparty/TinyXml2/CMakeLists.txt @@ -18,21 +18,8 @@ if(NOT MSVC) target_compile_options(${PROJECT_NAME} PUBLIC "-std=c++11") endif() set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "_d") -#install(TARGETS tinyxml2 -# RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} -# LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} -# ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) -#install(FILES tinyxml2.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +install(FILES "tinyxml2.h" DESTINATION "include/thirdparty/TinyXml2") -#foreach(p LIB INCLUDE) -# set(var CMAKE_INSTALL_${p}DIR) -# if(NOT IS_ABSOLUTE "${${var}}") -# set(${var} "${CMAKE_INSTALL_PREFIX}/${${var}}") -# endif() -#endforeach() +cgogn_create_package("${CMAKE_CURRENT_SOURCE_DIR}" "include") -#configure_file(tinyxml2.pc.in tinyxml2.pc @ONLY) -#install(FILES ${CMAKE_CURRENT_BINARY_DIR}/tinyxml2.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) - -#add_test(xmltest ${SAMPLE_NAME} COMMAND $) diff --git a/thirdparty/eigen-3.2.8/CMakeLists.txt b/thirdparty/eigen-3.2.8/CMakeLists.txt index a41af45b..4fae1922 100644 --- a/thirdparty/eigen-3.2.8/CMakeLists.txt +++ b/thirdparty/eigen-3.2.8/CMakeLists.txt @@ -3,7 +3,7 @@ set(CGOGN_THIRDPARTY_EIGEN3_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Eigen COMPONENT Eigen_headers - DESTINATION include + DESTINATION include/thirdparty PATTERN "*.in" EXCLUDE PATTERN "*.txt" EXCLUDE - PATTERN "*.cpp" EXCLUDE) \ No newline at end of file + PATTERN "*.cpp" EXCLUDE) diff --git a/thirdparty/google-benchmark/src/CMakeLists.txt b/thirdparty/google-benchmark/src/CMakeLists.txt index 811d0755..cce929fb 100644 --- a/thirdparty/google-benchmark/src/CMakeLists.txt +++ b/thirdparty/google-benchmark/src/CMakeLists.txt @@ -18,7 +18,10 @@ else() endif() add_library(benchmark ${SOURCE_FILES} ${RE_FILES}) - +# use of target_compile_options to have a transitive c++11 flag +if(NOT MSVC) + target_compile_options(benchmark PUBLIC "-std=c++11") +endif() set_target_properties(benchmark PROPERTIES OUTPUT_NAME "benchmark" @@ -47,5 +50,5 @@ install( install( DIRECTORY "${PROJECT_SOURCE_DIR}/include/benchmark" - DESTINATION include + DESTINATION include/thirdparty/ FILES_MATCHING PATTERN "*.*h") diff --git a/thirdparty/googletest-master/CMakeLists.txt b/thirdparty/googletest-master/CMakeLists.txt index d00f29a0..2738125f 100755 --- a/thirdparty/googletest-master/CMakeLists.txt +++ b/thirdparty/googletest-master/CMakeLists.txt @@ -14,3 +14,4 @@ if(BUILD_GMOCK) elseif(BUILD_GTEST) add_subdirectory( googletest ) endif() + diff --git a/thirdparty/googletest-master/googlemock/CMakeLists.txt b/thirdparty/googletest-master/googlemock/CMakeLists.txt index beb259a2..b5169036 100755 --- a/thirdparty/googletest-master/googlemock/CMakeLists.txt +++ b/thirdparty/googletest-master/googlemock/CMakeLists.txt @@ -92,6 +92,12 @@ cxx_library(gmock_main src/gmock-all.cc src/gmock_main.cc) +# use of target_compile_options to have a transitive c++11 flag +if(NOT MSVC) + target_compile_options(gmock PUBLIC "-std=c++11") + target_compile_options(gmock_main PUBLIC "-std=c++11") +endif() + # If the CMake version supports it, attach header directory information # to the targets for when we are part of a parent build (ie being pulled # in via add_subdirectory() rather than being a standalone build). @@ -106,7 +112,7 @@ endif() install(TARGETS gmock gmock_main DESTINATION lib) install(DIRECTORY ${gmock_SOURCE_DIR}/include/gmock - DESTINATION include) + DESTINATION include/thirdparty) ######################################################################## # diff --git a/thirdparty/googletest-master/googletest/CMakeLists.txt b/thirdparty/googletest-master/googletest/CMakeLists.txt index 621d0f04..0b2a0108 100755 --- a/thirdparty/googletest-master/googletest/CMakeLists.txt +++ b/thirdparty/googletest-master/googletest/CMakeLists.txt @@ -89,6 +89,10 @@ endif() # aggressive about warnings. cxx_library(gtest "${cxx_strict}" src/gtest-all.cc) cxx_library(gtest_main "${cxx_strict}" src/gtest_main.cc) +# use of target_compile_options to have a transitive c++11 flag +if(NOT MSVC) + target_compile_options(gtest PUBLIC "-std=c++11") +endif() target_link_libraries(gtest_main gtest) # If the CMake version supports it, attach header directory information @@ -105,7 +109,7 @@ endif() install(TARGETS gtest gtest_main DESTINATION lib) install(DIRECTORY ${gtest_SOURCE_DIR}/include/gtest - DESTINATION include) + DESTINATION include/thirdparty) ######################################################################## # diff --git a/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt b/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt index 1f535efb..50142946 100644 --- a/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt +++ b/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt @@ -1,9 +1,9 @@ set(CGOGN_THIRDPARTY_QOGLVIEWER_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH "QOGLViewer include directory") -PROJECT(QOGLViewer) -FIND_PACKAGE(OpenGL REQUIRED) -find_package(Qt5Widgets 5.4.0 REQUIRED) +project(QOGLViewer) +find_package(OpenGL REQUIRED) +find_package(Qt5 5.4.0 COMPONENTS Widgets REQUIRED) set(CMAKE_AUTOMOC ON) @@ -12,42 +12,42 @@ set(CMAKE_AUTOMOC ON) set(HEADER_FILES qoglviewer.h - camera.h - manipulatedFrame.h - manipulatedCameraFrame.h - frame.h - keyFrameInterpolator.h - + camera.h + manipulatedFrame.h + manipulatedCameraFrame.h + frame.h + keyFrameInterpolator.h config.h - constraint.h - mouseGrabber.h - quaternion.h - vec.h + constraint.h + mouseGrabber.h + quaternion.h + vec.h ) set(SOURCE_FILES qoglviewer.cpp - camera.cpp - manipulatedFrame.cpp - manipulatedCameraFrame.cpp - frame.cpp - saveSnapshot.cpp - constraint.cpp - keyFrameInterpolator.cpp - mouseGrabber.cpp - quaternion.cpp + camera.cpp + manipulatedFrame.cpp + manipulatedCameraFrame.cpp + frame.cpp + saveSnapshot.cpp + constraint.cpp + keyFrameInterpolator.cpp + mouseGrabber.cpp + quaternion.cpp vec.cpp ) -add_library(QOGLViewer SHARED ${HEADER_FILES} ${SOURCE_FILES}) -target_link_libraries(QOGLViewer ${OPENGL_LIBRARY} Qt5::Widgets) +add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) +target_link_libraries(${PROJECT_NAME} ${OPENGL_LIBRARY} ${Qt5Widgets_LIBRARIES}) +target_include_directories(${PROJECT_NAME} PRIVATE ${Qt5Widgets_INCLUDE_DIRS}) if(WIN32) - ADD_DEFINITIONS(-DCREATE_QGLVIEWER_DLL -DNOMINMAX /W3) + add_definitions(-DCREATE_QGLVIEWER_DLL -DNOMINMAX /W3) else() target_compile_options(${PROJECT_NAME} PUBLIC "-std=c++11") - ADD_DEFINITIONS(-fPIC) + add_definitions("-fPIC") endif() # for glu warning on mac @@ -56,6 +56,9 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") endif() +install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + DESTINATION "include/thirdparty/" + FILES_MATCHING PATTERN "*.h" +) - - +cgogn_create_package("${CMAKE_CURRENT_SOURCE_DIR}" "include") diff --git a/thirdparty/libQGLViewer/QOGLViewer/qoglviewer.cpp b/thirdparty/libQGLViewer/QOGLViewer/qoglviewer.cpp index 1793afcf..ae84deb8 100644 --- a/thirdparty/libQGLViewer/QOGLViewer/qoglviewer.cpp +++ b/thirdparty/libQGLViewer/QOGLViewer/qoglviewer.cpp @@ -173,6 +173,14 @@ QOGLViewer::QOGLViewer(QWidget* parent, Qt::WindowFlags flags) : QOpenGLWidget(parent, flags) { defaultConstructor(); } + +QOGLViewer::QOGLViewer(QOGLViewer* shared, QWidget* parent, Qt::WindowFlags flags) + : QOpenGLWidget(parent, flags) +{ + shared->context()->setShareContext(this->context()); + defaultConstructor(); +} + ///*! Same as QOGLViewer(), but a \c QGLContext can be provided so that viewers share GL contexts, even //with \c QGLContext sub-classes (use \p shareWidget otherwise). */ //QOGLViewer::QOGLViewer(QGLContext *context, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags flags) diff --git a/thirdparty/libQGLViewer/QOGLViewer/qoglviewer.h b/thirdparty/libQGLViewer/QOGLViewer/qoglviewer.h index 269c61e7..779c5ef0 100644 --- a/thirdparty/libQGLViewer/QOGLViewer/qoglviewer.h +++ b/thirdparty/libQGLViewer/QOGLViewer/qoglviewer.h @@ -62,7 +62,7 @@ callback mechanism). See the callback exampl complete implementation. \nosubgrouping */ -class QGLVIEWER_EXPORT QOGLViewer : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core +class QGLVIEWER_EXPORT QOGLViewer : public QOpenGLWidget, public QOpenGLFunctions_3_3_Core { Q_OBJECT @@ -71,6 +71,8 @@ class QGLVIEWER_EXPORT QOGLViewer : public QOpenGLWidget, protected QOpenGLFunct explicit QOGLViewer(QWidget* parent=0, Qt::WindowFlags flags=0); + explicit QOGLViewer(QOGLViewer* shared, QWidget* parent=0, Qt::WindowFlags flags=0); + virtual ~QOGLViewer(); diff --git a/thirdparty/lm6/CMakeLists.txt b/thirdparty/lm6/CMakeLists.txt index 8dc9f8df..1f5d3640 100644 --- a/thirdparty/lm6/CMakeLists.txt +++ b/thirdparty/lm6/CMakeLists.txt @@ -18,6 +18,11 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/tools) add_executable(transmesh transmesh.c) target_include_directories(transmesh PRIVATE $ + $ ) target_link_libraries(transmesh ${PROJECT_NAME}) set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "_d") + +install(FILES "libmesh6.h" DESTINATION "include/thirdparty/lm6") + +cgogn_create_package("${CMAKE_CURRENT_SOURCE_DIR}" "include") diff --git a/thirdparty/lm6/libmesh6.c b/thirdparty/lm6/libmesh6.c index ba2d6ce0..cde44336 100644 --- a/thirdparty/lm6/libmesh6.c +++ b/thirdparty/lm6/libmesh6.c @@ -664,6 +664,7 @@ long GmfSetKwd(int MshIdx, int KwdCod, ...) int GmfGetLin(int MshIdx, int KwdCod, ...) { + size_t nb_read; int i, j; float *FltSolTab; double *DblSolTab; @@ -714,7 +715,10 @@ int GmfGetLin(int MshIdx, int KwdCod, ...) else ScaDblWrd(msh, (unsigned char *)va_arg(VarArg, long *)); else if(kwd->fmt[i] == 'c') - fread(va_arg(VarArg, char *), WrdSiz, FilStrSiz, msh->hdl); + { + nb_read = fread(va_arg(VarArg, char *), WrdSiz, FilStrSiz, msh->hdl); + if (nb_read != FilStrSiz) printf("lm6 error reading file\n"); + } } }break; @@ -877,6 +881,7 @@ void GmfSetLin(int MshIdx, int KwdCod, ...) int GmfCpyLin(int InpIdx, int OutIdx, int KwdCod) { + size_t nb_read; char s[ WrdSiz * FilStrSiz ]; double d; float f; @@ -967,7 +972,10 @@ int GmfCpyLin(int InpIdx, int OutIdx, int KwdCod) if(InpMsh->typ & Asc) safe_fgets(s, WrdSiz * FilStrSiz, InpMsh->hdl); else - fread(s, WrdSiz, FilStrSiz, InpMsh->hdl); + { + nb_read = fread(s, WrdSiz, FilStrSiz, InpMsh->hdl); + if (nb_read != FilStrSiz) printf("lm6 error reading file\n"); + } if(OutMsh->typ & Asc) fprintf(OutMsh->hdl, "%s", s); diff --git a/thirdparty/ply/CMakeLists.txt b/thirdparty/ply/CMakeLists.txt index b276a2ac..0f8e3c71 100644 --- a/thirdparty/ply/CMakeLists.txt +++ b/thirdparty/ply/CMakeLists.txt @@ -14,3 +14,7 @@ set(SOURCE_FILES add_library(${PROJECT_NAME} STATIC ${HEADER_FILES} ${SOURCE_FILES}) set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "_d") + +install(FILES "ply.h" DESTINATION "include/thirdparty/ply") + +cgogn_create_package("${CMAKE_CURRENT_SOURCE_DIR}" "include") diff --git a/thirdparty/termcolor/CMakeLists.txt b/thirdparty/termcolor/CMakeLists.txt index c65700a9..cad9d42d 100644 --- a/thirdparty/termcolor/CMakeLists.txt +++ b/thirdparty/termcolor/CMakeLists.txt @@ -1 +1,3 @@ set(CGOGN_THIRDPARTY_TERMCOLOR_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH "Termcolor include directory") + +install(FILES "termcolor.hpp" DESTINATION "include/thirdparty/termcolor") diff --git a/thirdparty/termcolor/termcolor.hpp b/thirdparty/termcolor/termcolor.hpp index c3744b24..5af2eb60 100644 --- a/thirdparty/termcolor/termcolor.hpp +++ b/thirdparty/termcolor/termcolor.hpp @@ -53,7 +53,7 @@ namespace termcolor inline bool is_atty(const std::ostream& stream); #if defined(OS_WINDOWS) - void win_change_attributes(std::ostream& stream, int foreground, int background=-1); + inline void win_change_attributes(std::ostream& stream, int foreground, int background=-1); #endif } @@ -449,7 +449,7 @@ namespace termcolor #if defined(OS_MACOS) || defined(OS_LINUX) return ::isatty(fileno(std_stream)); #elif defined(OS_WINDOWS) - return ::_isatty(_fileno(std_stream)); + return ::_isatty(_fileno(std_stream))!=0; #endif } diff --git a/thirdparty/tetgen/CMakeLists.txt b/thirdparty/tetgen/CMakeLists.txt index ac23f548..35e48039 100644 --- a/thirdparty/tetgen/CMakeLists.txt +++ b/thirdparty/tetgen/CMakeLists.txt @@ -2,6 +2,10 @@ set(CGOGN_THIRDPARTY_TETGEN_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH # Set the minimum required version of cmake for a project. cmake_minimum_required(VERSION 3.0) +project(tet + LANGUAGES CXX +) + if(MSVC) add_definitions("-D_CRT_SECURE_NO_WARNINGS /W0") add_library(tet STATIC tetgen.h tetgen.cxx predicates.cxx) @@ -9,6 +13,14 @@ else(MSVC) add_library(tet SHARED tetgen.h tetgen.cxx predicates.cxx) endif(MSVC) +if(NOT MSVC) + target_compile_options(tet PUBLIC "-std=c++11") +endif() + +install(FILES "tetgen.h" DESTINATION "include/thirdparty/tetgen") + +cgogn_create_package("${CMAKE_CURRENT_SOURCE_DIR}" "include") + # Add an executable to the project using the specified source files. # add_executable(tetgen tetgen.cxx predicates.cxx) diff --git a/thirdparty/tetgen/tetgen.cxx b/thirdparty/tetgen/tetgen.cxx index 175653a9..4f26e871 100644 --- a/thirdparty/tetgen/tetgen.cxx +++ b/thirdparty/tetgen/tetgen.cxx @@ -2131,6 +2131,7 @@ bool tetgenio::load_vtk(char* filebasename) int nn = -1; int nn_old = -1; int i, j; + int nb_read; bool ImALittleEndian = !testIsBigEndian(); int smallestidx = 0; @@ -2177,18 +2178,20 @@ bool tetgenio::load_vtk(char* filebasename) for(i = 0; i < nverts; i++) { coord = &pointlist[i * 3]; if(!strcmp(fmt, "double")) { - fread((char*)(&(coord[0])), sizeof(double), 1, fp); - fread((char*)(&(coord[1])), sizeof(double), 1, fp); - fread((char*)(&(coord[2])), sizeof(double), 1, fp); + nb_read = fread((char*)(&(coord[0])), sizeof(double), 1, fp); + nb_read += fread((char*)(&(coord[1])), sizeof(double), 1, fp); + nb_read += fread((char*)(&(coord[2])), sizeof(double), 1, fp); + if (nb_read != 3) printf("Error: can not read vertex position!\n"); if(ImALittleEndian){ swapBytes((unsigned char *) &(coord[0]), sizeof(coord[0])); swapBytes((unsigned char *) &(coord[1]), sizeof(coord[1])); swapBytes((unsigned char *) &(coord[2]), sizeof(coord[2])); } } else if(!strcmp(fmt, "float")) { - fread((char*)(&_x), sizeof(float), 1, fp); - fread((char*)(&_y), sizeof(float), 1, fp); - fread((char*)(&_z), sizeof(float), 1, fp); + nb_read = fread((char*)(&_x), sizeof(float), 1, fp); + nb_read += fread((char*)(&_y), sizeof(float), 1, fp); + nb_read += fread((char*)(&_z), sizeof(float), 1, fp); + if (nb_read != 3) printf("Error: can not read vertex position!\n"); if(ImALittleEndian){ swapBytes((unsigned char *) &_x, sizeof(_x)); swapBytes((unsigned char *) &_y, sizeof(_y)); @@ -2237,7 +2240,8 @@ bool tetgenio::load_vtk(char* filebasename) if(!strcmp(mode, "BINARY")) { for(i = 0; i < nfaces; i++){ - fread((char*)(&nn), sizeof(int), 1, fp); + nb_read = fread((char*)(&nn), sizeof(int), 1, fp); + if (nb_read != 1) printf("Error: can not read nb faces!\n"); if(ImALittleEndian){ swapBytes((unsigned char *) &nn, sizeof(nn)); } @@ -2249,9 +2253,10 @@ bool tetgenio::load_vtk(char* filebasename) } if(nn == 3){ - fread((char*)(&id1), sizeof(int), 1, fp); - fread((char*)(&id2), sizeof(int), 1, fp); - fread((char*)(&id3), sizeof(int), 1, fp); + nb_read = fread((char*)(&id1), sizeof(int), 1, fp); + nb_read += fread((char*)(&id2), sizeof(int), 1, fp); + nb_read += fread((char*)(&id3), sizeof(int), 1, fp); + if (nb_read != 3) printf("Error: can not read faces!\n"); if(ImALittleEndian){ swapBytes((unsigned char *) &id1, sizeof(id1)); swapBytes((unsigned char *) &id2, sizeof(id2));