diff --git a/src/Unittests/CMakeLists.txt b/src/Unittests/CMakeLists.txt index a6ea5e7b..a8b02724 100644 --- a/src/Unittests/CMakeLists.txt +++ b/src/Unittests/CMakeLists.txt @@ -30,22 +30,28 @@ if ( OPENMESH_BUILD_UNIT_TESTS ) FILE(GLOB UNITTEST_SRC *.cc) # Create unittest executable acg_add_executable(unittests ${UNITTEST_SRC}) + acg_add_executable(unittests_customvec ${UNITTEST_SRC}) + target_compile_definitions(unittests_customvec PRIVATE TEST_CUSTOM_TRAITS) # For the unittest we don't want the install rpath as set by acg_add_executable - set_target_properties ( unittests PROPERTIES BUILD_WITH_INSTALL_RPATH 0 ) + set_target_properties ( unittests PROPERTIES BUILD_WITH_INSTALL_RPATH 0 ) + set_target_properties ( unittests_customvec PROPERTIES BUILD_WITH_INSTALL_RPATH 0 ) # Set output directory to ${BINARY_DIR}/Unittests set (OUTPUT_DIR "${CMAKE_BINARY_DIR}/Unittests") set_target_properties(unittests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIR}) + set_target_properties(unittests_customvec PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIR}) foreach(CONFIG ${CMAKE_CONFIGURATION_TYPES}) string(TOUPPER ${CONFIG} UPCONFIG) set_target_properties(unittests PROPERTIES RUNTIME_OUTPUT_DIRECTORY_${UPCONFIG} ${OUTPUT_DIR}) + set_target_properties(unittests_customvec PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIR}) endforeach() if ( NOT WIN32) # Link against all necessary libraries target_link_libraries(unittests OpenMeshCore OpenMeshTools ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES} pthread) + target_link_libraries(unittests_customvec OpenMeshCore OpenMeshTools ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES} pthread) @@ -56,6 +62,7 @@ if ( OPENMESH_BUILD_UNIT_TESTS ) endif() target_link_libraries(unittests OpenMeshCore OpenMeshTools ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES}) + target_link_libraries(unittests_customvec OpenMeshCore OpenMeshTools ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES}) endif() @@ -63,9 +70,11 @@ if ( OPENMESH_BUILD_UNIT_TESTS ) if ( NOT WIN32 ) # Set compiler flags set_target_properties(unittests PROPERTIES COMPILE_FLAGS "-g -pedantic -Wno-long-long") + set_target_properties(unittests_customvec PROPERTIES COMPILE_FLAGS "-g -pedantic -Wno-long-long") else() # Set compiler flags set_target_properties(unittests PROPERTIES COMPILE_FLAGS "" ) + set_target_properties(unittests_customvec PROPERTIES COMPILE_FLAGS "-g -pedantic -Wno-long-long") endif() @@ -80,10 +89,16 @@ if ( OPENMESH_BUILD_UNIT_TESTS ) "$" "${CMAKE_BINARY_DIR}/Unittests/$" COMMENT "Copying OpenMesh targets to unittests directory") + add_custom_command(TARGET unittests_customvec POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy + "$" + "${CMAKE_BINARY_DIR}/Unittests/$" + COMMENT "Copying OpenMesh targets to unittests directory") endforeach(TAR) endif() acg_copy_after_build(unittests ${CMAKE_CURRENT_SOURCE_DIR}/TestFiles ${CMAKE_BINARY_DIR}/Unittests/) + acg_copy_after_build(unittests_customvec ${CMAKE_CURRENT_SOURCE_DIR}/TestFiles ${CMAKE_BINARY_DIR}/Unittests/) add_test(NAME AllTestsIn_OpenMesh_tests WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/Unittests" COMMAND "${CMAKE_BINARY_DIR}/Unittests/unittests") diff --git a/src/Unittests/unittests_common.hh b/src/Unittests/unittests_common.hh index cbabb9cb..0d095701 100644 --- a/src/Unittests/unittests_common.hh +++ b/src/Unittests/unittests_common.hh @@ -7,8 +7,13 @@ #include #include +#ifdef TEST_CUSTOM_TRAITS +#include +#else struct CustomTraits : public OpenMesh::DefaultTraits { }; +#endif + typedef OpenMesh::TriMesh_ArrayKernelT Mesh; diff --git a/src/Unittests/unittests_common_customtraits.hh b/src/Unittests/unittests_common_customtraits.hh new file mode 100644 index 00000000..a53f724d --- /dev/null +++ b/src/Unittests/unittests_common_customtraits.hh @@ -0,0 +1,145 @@ +#ifndef UNITTESTS_COMMON_DUMMYTRAITS +#define UNITTESTS_COMMON_DUMMYTRAITS +#include +#include + +namespace Custom { + +/// A Vector class with the absolute minimum of built-in methods to test the +/// interface expected from Vectors used in Traits +template class Vec { + public: + // Constructor with DIM components + template ::type, + typename = typename std::enable_if< + are_convertible_to::value>::type> + constexpr Vec(T v, Ts... vs) + : data{{static_cast(v), static_cast(vs)...}} { + static_assert(sizeof...(Ts)+1 == DIM, + "Invalid number of components specified in constructor."); + static_assert(are_convertible_to::value, + "Not all components are convertible to Scalar."); + } + + constexpr Vec() = default; + constexpr Vec(Vec const &) = default; + + float &operator[](int i) { return data[i]; } + float operator[](int i) const { return data[i]; } + + private: + std::array data; +}; + +template bool operator==(Vec const &lhs, Vec const &rhs) { + for (int i = 0; i < DIM; i++) + if (lhs[i] != rhs[i]) return false; + return true; +} + +template +Vec operator+(Vec const &lhs, Vec const &rhs) { + Vec result; + for (int i = 0; i < DIM; i++) + result[i] = lhs[i] + rhs[i]; + return result; +} + +template +Vec operator-(Vec const &lhs, Vec const &rhs) { + Vec result; + for (int i = 0; i < DIM; i++) + result[i] = lhs[i] - rhs[i]; + return result; +} + +template Vec operator*(Vec const &lhs, float rhs) { + Vec result; + for (int i = 0; i < DIM; i++) + result[i] = lhs[i] * rhs; + return result; +} + +template Vec operator*(float lhs, Vec const &rhs) { + return rhs * lhs; +} + +template Vec operator/(Vec const &lhs, float rhs) { + Vec result; + for (int i = 0; i < DIM; i++) + result[i] = lhs[i] / rhs; + return result; +} + +template Vec &operator+=(Vec &lhs, Vec const &rhs) { + return lhs = lhs + rhs; +} +template Vec &operator-=(Vec &lhs, Vec const &rhs) { + return lhs = lhs - rhs; +} +template Vec &operator*=(Vec &lhs, float rhs) { + return lhs = lhs * rhs; +} +template Vec &operator/=(Vec &lhs, float rhs) { + return lhs = lhs / rhs; +} + +template float norm(Vec const &v) { + float sum = 0.0f; + for (int i = 0; i < DIM; i++) + sum += v[i] * v[i]; + return std::sqrt(sum); +} + +template Vec &normalize(Vec &v) { return v /= norm(v); } +template Vec &vectorize(Vec &v, float val) { + for (int i = 0; i < DIM; i++) + v[i] = val; + return v; +} + +template Vec &minimize(Vec &v1, Vec const &v2) { + for (int i = 0; i < DIM; i++) + v1[i] = std::min(v1[i], v2[i]); + return v1; +} + +template Vec &maximize(Vec &v1, Vec const &v2) { + for (int i = 0; i < DIM; i++) + v1[i] = std::max(v1[i], v2[i]); + return v1; +} + +template float dot(Vec const &v1, Vec const &v2) { + float sum = 0.f; + for (int i = 0; i < DIM; i++) + sum += v1[i] * v2[i]; + return sum; +} + +inline Vec<3> cross(Vec<3> const &v1, Vec<3> const &v2) { + return {v1[1] * v2[2] - v1[2] * v2[1], // + v1[2] * v2[0] - v1[0] * v2[2], // + v1[0] * v2[1] - v1[1] * v2[0]}; +} +} + +namespace OpenMesh { +template struct vector_traits> { + using vector_type = Custom::Vec; + using value_type = float; + static const size_t size_ = DIM; + static size_t size() { return size_; } +}; +} + +struct CustomTraits : public OpenMesh::DefaultTraits { + typedef Custom::Vec<3> Point; + typedef Custom::Vec<3> Normal; + + typedef Custom::Vec<2> TexCoord2D; + typedef Custom::Vec<3> TexCoord3D; +}; + +#endif // UNITTESTS_COMMON_DUMMYTRAITS