diff --git a/CMakeLists.txt b/CMakeLists.txt index c05a6284..ac86b67e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,14 @@ if("${PROJECT_NAME}" STREQUAL "") project (OpenMesh) endif() +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "6.0" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "4.9" OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL "4.9") + message(WARNING "Your version of GCC contains an optimizer bug. Please verify that you do not use -O3!") + string(REPLACE "-O3" "-O2" CMAKE_CXX_FLAGS_RELEASE_NEW "${CMAKE_CXX_FLAGS_RELEASE}") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE_NEW}" CACHE STRING "" FORCE) + endif() +endif() + if ( WIN32 ) # This is the base directory for windows library search used in the finders we ship. set(CMAKE_WINDOWS_LIBS_DIR "c:/libs" CACHE STRING "Default Library search dir on windows." ) diff --git a/Doc/changelog.docu b/Doc/changelog.docu index cf4bb4e4..d940fae4 100644 --- a/Doc/changelog.docu +++ b/Doc/changelog.docu @@ -9,6 +9,28 @@ 6.3 (?/?/?) +Core + + +IO + + + +General + + +Build System + + 6.2 (2016/07/11) diff --git a/src/OpenMesh/Apps/Decimating/DecimaterViewerWidget.hh b/src/OpenMesh/Apps/Decimating/DecimaterViewerWidget.hh index dd54f59d..9b8fa4d9 100644 --- a/src/OpenMesh/Apps/Decimating/DecimaterViewerWidget.hh +++ b/src/OpenMesh/Apps/Decimating/DecimaterViewerWidget.hh @@ -114,7 +114,7 @@ public: typedef Decimater::ModNormalFlippingT< mesh_t >::Handle mod_nf_t; // object types -#if _MSC_VER >= 1900 || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) +#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) typedef std::unique_ptr< decimater_t > decimater_o; #else typedef std::auto_ptr< decimater_t > decimater_o; diff --git a/src/OpenMesh/Apps/Unsupported/OsgViewer/osgviewer.cc b/src/OpenMesh/Apps/Unsupported/OsgViewer/osgviewer.cc index c5f8a9d0..e5d4a87f 100644 --- a/src/OpenMesh/Apps/Unsupported/OsgViewer/osgviewer.cc +++ b/src/OpenMesh/Apps/Unsupported/OsgViewer/osgviewer.cc @@ -131,7 +131,7 @@ public: bool bind( osg::GeometryPtr geo ) { - #if _MSC_VER >= 1900 || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) + #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) std::unique_ptr obj(new mesh_t); #else std::auto_ptr obj(new mesh_t); diff --git a/src/OpenMesh/Apps/VDProgMesh/Analyzer/vdpmanalyzer.cc b/src/OpenMesh/Apps/VDProgMesh/Analyzer/vdpmanalyzer.cc index b261c6b6..c939fb39 100644 --- a/src/OpenMesh/Apps/VDProgMesh/Analyzer/vdpmanalyzer.cc +++ b/src/OpenMesh/Apps/VDProgMesh/Analyzer/vdpmanalyzer.cc @@ -851,7 +851,7 @@ compute_screen_space_error(VHierarchyNodeHandle node_handle, VHierarchyNodeHandl Vec3f residual; Vec3f res; Vec3f lp; -#if (_MSC_VER >= 1900 ) +#if ((defined(_MSC_VER) && (_MSC_VER >= 1900)) ) // Workaround for internal compiler error Vec3f tri[3]{ {},{},{} }; #else diff --git a/src/OpenMesh/Core/CMakeLists.txt b/src/OpenMesh/Core/CMakeLists.txt index 67c37ea1..83b11eb2 100644 --- a/src/OpenMesh/Core/CMakeLists.txt +++ b/src/OpenMesh/Core/CMakeLists.txt @@ -3,7 +3,6 @@ include (ACGCommon) include_directories ( ../.. ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/src ) # source code directories diff --git a/src/OpenMesh/Core/Geometry/Vector11T.hh b/src/OpenMesh/Core/Geometry/Vector11T.hh index 28ad0b71..0f771fd4 100644 --- a/src/OpenMesh/Core/Geometry/Vector11T.hh +++ b/src/OpenMesh/Core/Geometry/Vector11T.hh @@ -366,8 +366,8 @@ class VectorT { template auto operator% (const VectorT &_rhs) const -> typename std::enable_ifvalues_[0] * _rhs[0] - - this->values_[0] * _rhs[0]), + VectorT>::type { return { values_[1] * _rhs[2] - values_[2] * _rhs[1], diff --git a/src/OpenMesh/Core/Geometry/VectorT.hh b/src/OpenMesh/Core/Geometry/VectorT.hh index b79882b4..d8c8f2b1 100644 --- a/src/OpenMesh/Core/Geometry/VectorT.hh +++ b/src/OpenMesh/Core/Geometry/VectorT.hh @@ -60,7 +60,7 @@ // macro expansion and preprocessor defines // don't work properly. -#if (_MSC_VER >= 1900 || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)) && !defined(OPENMESH_VECTOR_LEGACY) +#if ((defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)) && !defined(OPENMESH_VECTOR_LEGACY) #include "Vector11T.hh" #else #ifndef DOXYGEN diff --git a/src/OpenMesh/Core/IO/reader/STLReader.cc b/src/OpenMesh/Core/IO/reader/STLReader.cc index 8e4b9b63..6dd8569b 100644 --- a/src/OpenMesh/Core/IO/reader/STLReader.cc +++ b/src/OpenMesh/Core/IO/reader/STLReader.cc @@ -55,12 +55,20 @@ #include #include +#include // OpenMesh #include #include #include +//comppare strings crossplatform ignorign case +#ifdef _WIN32 + #define strnicmp _strnicmp +#else + #define strnicmp strncasecmp +#endif + //=== NAMESPACES ============================================================== @@ -447,41 +455,62 @@ _STLReader_::STL_Type _STLReader_:: check_stl_type(const std::string& _filename) const { - // assume it's binary stl, then file size is known from #triangles - // if size matches, it's really binary + + // open file + std::ifstream ifs (_filename.c_str(), std::ifstream::binary); + if(!ifs.good()) + { + omerr() << "could not open file" << _filename << std::endl; + return NONE; + } + + //find first non whitespace character + std::string line = ""; + std::size_t firstChar; + while(line.empty() && ifs.good()) + { + std::getline(ifs,line); + firstChar = line.find_first_not_of("\t "); + } + + //check for ascii keyword solid + if(strnicmp("solid",&line[firstChar],5) == 0) + { + return STLA; + } + ifs.close(); + + //if the file does not start with solid it is probably STLB + //check the file size to verify it. + + //open the file + FILE* in = fopen(_filename.c_str(), "rb"); + if (!in) return NONE; + + // determine endian mode + union { unsigned int i; unsigned char c[4]; } endian_test; + endian_test.i = 1; + bool swapFlag = (endian_test.c[3] == 1); - // open file - FILE* in = fopen(_filename.c_str(), "rb"); - if (!in) return NONE; + // read number of triangles + char dummy[100]; + fread(dummy, 1, 80, in); + size_t nT = read_int(in, swapFlag); - // determine endian mode - union { unsigned int i; unsigned char c[4]; } endian_test; - endian_test.i = 1; - bool swapFlag = (endian_test.c[3] == 1); + // compute file size from nT + size_t binary_size = 84 + nT*50; + // get actual file size + size_t file_size(0); + rewind(in); + while (!feof(in)) + file_size += fread(dummy, 1, 100, in); + fclose(in); - // read number of triangles - char dummy[100]; - fread(dummy, 1, 80, in); - size_t nT = read_int(in, swapFlag); - - - // compute file size from nT - size_t binary_size = 84 + nT*50; - - - // get actual file size - size_t file_size(0); - rewind(in); - while (!feof(in)) - file_size += fread(dummy, 1, 100, in); - fclose(in); - - - // if sizes match -> it's STLB - return (binary_size == file_size ? STLB : STLA); + // if sizes match -> it's STLB + return (binary_size == file_size ? STLB : NONE); } diff --git a/src/OpenMesh/Core/Mesh/IteratorsT.hh b/src/OpenMesh/Core/Mesh/IteratorsT.hh index d12e5eb0..ca0d31e9 100644 --- a/src/OpenMesh/Core/Mesh/IteratorsT.hh +++ b/src/OpenMesh/Core/Mesh/IteratorsT.hh @@ -170,7 +170,7 @@ class GenericIteratorT { return cpy; } -#if (_MSC_VER >= 1900 || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)) && !defined(OPENMESH_VECTOR_LEGACY) +#if ((defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)) && !defined(OPENMESH_VECTOR_LEGACY) template auto operator+=(int amount) -> typename std::enable_if< diff --git a/src/OpenMesh/Core/System/config.h b/src/OpenMesh/Core/System/config.h index b247f812..8662bde1 100644 --- a/src/OpenMesh/Core/System/config.h +++ b/src/OpenMesh/Core/System/config.h @@ -102,7 +102,7 @@ typedef unsigned int uint; -#if (_MSC_VER >= 1900 || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)) +#if ((defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)) #define OM_HAS_HASH #endif diff --git a/src/OpenMesh/Core/System/mostream.hh b/src/OpenMesh/Core/System/mostream.hh index f079b454..c197a49b 100644 --- a/src/OpenMesh/Core/System/mostream.hh +++ b/src/OpenMesh/Core/System/mostream.hh @@ -70,7 +70,7 @@ #include #include -#if _MSC_VER >= 1900 || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ ) +#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ ) #include #endif @@ -189,7 +189,7 @@ protected: virtual int sync() { // If working on multiple threads, we need to serialize the output correctly (requires c++11 headers) - #if _MSC_VER >= 1900 || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ ) + #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ ) std::lock_guard lck (serializer_); #endif @@ -214,7 +214,7 @@ protected: char c = traits_type::to_char_type(_c); // If working on multiple threads, we need to serialize the output correctly (requires c++11 headers) - #if _MSC_VER >= 1900 || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ ) + #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ ) { std::lock_guard lck (serializer_); buffer_.push_back(c); @@ -264,7 +264,7 @@ private: bool enabled_; // If working on multiple threads, we need to serialize the output correctly (requires c++11 headers) - #if _MSC_VER >= 1900 || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ ) + #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ ) std::mutex serializer_; #endif diff --git a/src/OpenMesh/Core/Utils/PropertyContainer.hh b/src/OpenMesh/Core/Utils/PropertyContainer.hh index 53584bb2..ae8d9dfc 100644 --- a/src/OpenMesh/Core/Utils/PropertyContainer.hh +++ b/src/OpenMesh/Core/Utils/PropertyContainer.hh @@ -204,7 +204,7 @@ public: * In C++11 an beyond we can introduce more efficient and more legible * implementations of the following methods. */ -#if (_MSC_VER >= 1900 || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)) && !defined(OPENMESH_VECTOR_LEGACY) +#if ((defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)) && !defined(OPENMESH_VECTOR_LEGACY) /** * Reserves space for \p _n elements in all property vectors. */ diff --git a/src/OpenMesh/Core/Utils/PropertyManager.hh b/src/OpenMesh/Core/Utils/PropertyManager.hh index f05903a9..2f38ca40 100644 --- a/src/OpenMesh/Core/Utils/PropertyManager.hh +++ b/src/OpenMesh/Core/Utils/PropertyManager.hh @@ -92,7 +92,7 @@ namespace OpenMesh { */ template class PropertyManager { -#if _MSC_VER >= 1900 || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) +#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) public: PropertyManager(const PropertyManager&) = delete; PropertyManager& operator=(const PropertyManager&) = delete; @@ -167,7 +167,7 @@ class PropertyManager { MeshT &getMesh() const { return *mesh_; } -#if _MSC_VER >= 1900 || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) +#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) /// Only for pre C++11 compatibility. typedef PropertyManager Proxy; @@ -208,6 +208,42 @@ class PropertyManager { return std::move(pm); } + /** + * Like createIfNotExists() with two parameters except, if the property + * doesn't exist, it is initialized with the supplied value over + * the supplied range after creation. If the property already exists, + * this method has the exact same effect as the two parameter version. + * Lifecycle management is disabled in any case. + * + * @see makePropertyManagerFromExistingOrNew + */ + template + static PropertyManager createIfNotExists(MeshT &mesh, const char *propname, + const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end, + const PROP_VALUE &init_value) { + const bool exists = propertyExists(mesh, propname); + PropertyManager pm(mesh, propname, exists); + pm.retain(); + if (!exists) + pm.set_range(begin, end, init_value); + return std::move(pm); + } + + /** + * Like createIfNotExists() with two parameters except, if the property + * doesn't exist, it is initialized with the supplied value over + * the supplied range after creation. If the property already exists, + * this method has the exact same effect as the two parameter version. + * Lifecycle management is disabled in any case. + * + * @see makePropertyManagerFromExistingOrNew + */ + template + static PropertyManager createIfNotExists(MeshT &mesh, const char *propname, + const ITERATOR_RANGE &range, const PROP_VALUE &init_value) { + return createIfNotExists( + mesh, propname, range.begin(), range.end(), init_value); + } PropertyManager duplicate(const char *clone_name) { PropertyManager pm(*mesh_, clone_name, false); @@ -267,6 +303,27 @@ class PropertyManager { return (Proxy)pm; } + /** + * Like createIfNotExists() with two parameters except, if the property + * doesn't exist, it is initialized with the supplied value over + * the supplied range after creation. If the property already exists, + * this method has the exact same effect as the two parameter version. + * Lifecycle management is disabled in any case. + * + * @see makePropertyManagerFromExistingOrNew + */ + template + static Proxy createIfNotExists(MeshT &mesh, const char *propname, + const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end, + const PROP_VALUE &init_value) { + const bool exists = propertyExists(mesh, propname); + PropertyManager pm(mesh, propname, exists); + pm.retain(); + if (!exists) + pm.set_range(begin, end, init_value); + return (Proxy)pm; + } + Proxy duplicate(const char *clone_name) { PropertyManager pm(*mesh_, clone_name, false); pm.mesh_->property(pm.prop_) = mesh_->property(prop_); @@ -353,6 +410,14 @@ class PropertyManager { (*this)[*begin] = value; } +#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) + template + void set_range(const HandleTypeIteratorRange &range, + const PROP_VALUE &value) { + set_range(range.begin(), range.end(), value); + } +#endif + /** * Conveniently transfer the values managed by one property manager * onto the values managed by a different property manager. @@ -466,5 +531,47 @@ PropertyManager makePropertyManagerFromExistingOrNew(MeshT &mes return PropertyManager::createIfNotExists(mesh, propname); } +/** \relates PropertyManager + * Like the two parameter version of makePropertyManagerFromExistingOrNew() + * except it initializes the property with the specified value over the + * specified range if it needs to be created. If the property already exists, + * this function has the exact same effect as the two parameter version. + * + * Creates a non-owning wrapper for a mesh property (no lifecycle management). + * If the given property does not exist, it is created. + * + * Intended for creating or accessing persistent properties. + */ +template +PropertyManager makePropertyManagerFromExistingOrNew( + MeshT &mesh, const char *propname, + const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end, + const PROP_VALUE &init_value) { + return PropertyManager::createIfNotExists( + mesh, propname, begin, end, init_value); +} + +/** \relates PropertyManager + * Like the two parameter version of makePropertyManagerFromExistingOrNew() + * except it initializes the property with the specified value over the + * specified range if it needs to be created. If the property already exists, + * this function has the exact same effect as the two parameter version. + * + * Creates a non-owning wrapper for a mesh property (no lifecycle management). + * If the given property does not exist, it is created. + * + * Intended for creating or accessing persistent properties. + */ +template +PropertyManager makePropertyManagerFromExistingOrNew( + MeshT &mesh, const char *propname, + const ITERATOR_RANGE &range, + const PROP_VALUE &init_value) { + return makePropertyManagerFromExistingOrNew( + mesh, propname, range.begin(), range.end(), init_value); +} + } /* namespace OpenMesh */ #endif /* PROPERTYMANAGER_HH_ */ diff --git a/src/OpenMesh/Tools/Decimater/DecimaterT.cc b/src/OpenMesh/Tools/Decimater/DecimaterT.cc index 31c47103..a7e18dce 100644 --- a/src/OpenMesh/Tools/Decimater/DecimaterT.cc +++ b/src/OpenMesh/Tools/Decimater/DecimaterT.cc @@ -78,7 +78,7 @@ template DecimaterT::DecimaterT(Mesh& _mesh) : BaseDecimaterT(_mesh), mesh_(_mesh), -#if _MSC_VER >= 1900 || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ ) +#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ ) heap_(nullptr) #else heap_(NULL) @@ -178,7 +178,7 @@ size_t DecimaterT::decimate(size_t _n_collapses) { // initialize heap HeapInterface HI(mesh_, priority_, heap_position_); -#if _MSC_VER >= 1900 || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ ) +#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ ) heap_ = std::unique_ptr(new DeciHeap(HI)); #else heap_ = std::auto_ptr(new DeciHeap(HI)); @@ -282,7 +282,7 @@ size_t DecimaterT::decimate_to_faces(size_t _nv, size_t _nf) { // initialize heap HeapInterface HI(mesh_, priority_, heap_position_); - #if _MSC_VER >= 1900 || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ ) + #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ ) heap_ = std::unique_ptr(new DeciHeap(HI)); #else heap_ = std::auto_ptr(new DeciHeap(HI)); diff --git a/src/OpenMesh/Tools/Decimater/DecimaterT.hh b/src/OpenMesh/Tools/Decimater/DecimaterT.hh index c31b2be6..2c71a093 100644 --- a/src/OpenMesh/Tools/Decimater/DecimaterT.hh +++ b/src/OpenMesh/Tools/Decimater/DecimaterT.hh @@ -195,7 +195,7 @@ private: //------------------------------------------------------- private data Mesh& mesh_; // heap - #if _MSC_VER >= 1900 || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ ) + #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ ) std::unique_ptr heap_; #else std::auto_ptr heap_; diff --git a/src/OpenMesh/Tools/Utils/HeapT.hh b/src/OpenMesh/Tools/Utils/HeapT.hh index 47e0b184..5a28ff7f 100644 --- a/src/OpenMesh/Tools/Utils/HeapT.hh +++ b/src/OpenMesh/Tools/Utils/HeapT.hh @@ -79,7 +79,7 @@ #include "Config.hh" #include #include -#if _MSC_VER >= 1900 || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) +#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) #include #endif @@ -150,7 +150,7 @@ public: /// Constructor HeapT() : HeapVector() {} -#if _MSC_VER >= 1900 || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) +#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) /// Construct with a given \c HeapIterface. HeapT(HeapInterface _interface) : HeapVector(), interface_(std::move(_interface)) diff --git a/src/OpenMesh/Tools/VDPM/ViewingParameters.cc b/src/OpenMesh/Tools/VDPM/ViewingParameters.cc index 2036e2fb..065c9319 100644 --- a/src/OpenMesh/Tools/VDPM/ViewingParameters.cc +++ b/src/OpenMesh/Tools/VDPM/ViewingParameters.cc @@ -92,7 +92,7 @@ update_viewing_configurations() Vec3f trans; // Workaround for internal compiler error on Visual Studio 2015 Update 1 -#if (_MSC_VER >= 1900 ) +#if ((defined(_MSC_VER) && (_MSC_VER >= 1900)) ) Vec3f inv_rot[3]{ {},{},{} }; Vec3f normal[4]{ {},{},{},{} }; #else diff --git a/src/Python/Vector.hh b/src/Python/Vector.hh index 933b730a..31e3ff34 100644 --- a/src/Python/Vector.hh +++ b/src/Python/Vector.hh @@ -190,4 +190,4 @@ void expose_vec(const char *_name) { } // namespace OpenMesh } // namespace Python -#endif +#endif \ No newline at end of file diff --git a/src/Unittests/unittests_cpp_11_features.cc b/src/Unittests/unittests_cpp_11_features.cc index f50e0a9c..a001cf9c 100644 --- a/src/Unittests/unittests_cpp_11_features.cc +++ b/src/Unittests/unittests_cpp_11_features.cc @@ -53,7 +53,7 @@ class OpenMesh_Triangle : public OpenMeshBase { * ==================================================================== */ -#if _MSC_VER >= 1900 || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) +#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) /* */ diff --git a/src/Unittests/unittests_propertymanager.cc b/src/Unittests/unittests_propertymanager.cc index 5ee75c62..7a1f1d21 100644 --- a/src/Unittests/unittests_propertymanager.cc +++ b/src/Unittests/unittests_propertymanager.cc @@ -60,36 +60,76 @@ TEST_F(OpenMeshPropertyManager, set_range_bool) { face_vhandles.push_back(vhandle[3]); mesh_.add_face(face_vhandles); - OpenMesh::PropertyManager< - OpenMesh::VPropHandleT, Mesh> pm_v_bool(mesh_, "pm_v_bool"); - pm_v_bool.set_range(mesh_.vertices_begin(), mesh_.vertices_end(), false); - for (int i = 0; i < 4; ++i) - ASSERT_FALSE(pm_v_bool[vhandle[i]]); - pm_v_bool.set_range(mesh_.vertices_begin(), mesh_.vertices_end(), true); - for (int i = 0; i < 4; ++i) - ASSERT_TRUE(pm_v_bool[vhandle[i]]); + { + OpenMesh::PropertyManager< + OpenMesh::VPropHandleT, Mesh> pm_v_bool(mesh_, "pm_v_bool"); + pm_v_bool.set_range(mesh_.vertices_begin(), mesh_.vertices_end(), false); + for (int i = 0; i < 4; ++i) + ASSERT_FALSE(pm_v_bool[vhandle[i]]); + pm_v_bool.set_range(mesh_.vertices_begin(), mesh_.vertices_end(), true); + for (int i = 0; i < 4; ++i) + ASSERT_TRUE(pm_v_bool[vhandle[i]]); - OpenMesh::PropertyManager< - OpenMesh::EPropHandleT, Mesh> pm_e_bool(mesh_, "pm_e_bool"); - pm_e_bool.set_range(mesh_.edges_begin(), mesh_.edges_end(), false); - for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end(); - e_it != f_end; ++e_it) - ASSERT_FALSE(pm_e_bool[*e_it]); - pm_e_bool.set_range(mesh_.edges_begin(), mesh_.edges_end(), true); - for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end(); - e_it != f_end; ++e_it) - ASSERT_TRUE(pm_e_bool[*e_it]); + OpenMesh::PropertyManager< + OpenMesh::EPropHandleT, Mesh> pm_e_bool(mesh_, "pm_e_bool"); + pm_e_bool.set_range(mesh_.edges_begin(), mesh_.edges_end(), false); + for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end(); + e_it != f_end; ++e_it) + ASSERT_FALSE(pm_e_bool[*e_it]); + pm_e_bool.set_range(mesh_.edges_begin(), mesh_.edges_end(), true); + for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end(); + e_it != f_end; ++e_it) + ASSERT_TRUE(pm_e_bool[*e_it]); - OpenMesh::PropertyManager< - OpenMesh::FPropHandleT, Mesh> pm_f_bool(mesh_, "pm_f_bool"); - pm_f_bool.set_range(mesh_.faces_begin(), mesh_.faces_end(), false); - for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end(); - f_it != f_end; ++f_it) - ASSERT_FALSE(pm_f_bool[*f_it]); - pm_f_bool.set_range(mesh_.faces_begin(), mesh_.faces_end(), true); - for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end(); - f_it != f_end; ++f_it) - ASSERT_TRUE(pm_f_bool[*f_it]); + OpenMesh::PropertyManager< + OpenMesh::FPropHandleT, Mesh> pm_f_bool(mesh_, "pm_f_bool"); + pm_f_bool.set_range(mesh_.faces_begin(), mesh_.faces_end(), false); + for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end(); + f_it != f_end; ++f_it) + ASSERT_FALSE(pm_f_bool[*f_it]); + pm_f_bool.set_range(mesh_.faces_begin(), mesh_.faces_end(), true); + for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end(); + f_it != f_end; ++f_it) + ASSERT_TRUE(pm_f_bool[*f_it]); + } + +#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) + /* + * Same thing again, this time with C++11 ranges. + */ + { + OpenMesh::PropertyManager< + OpenMesh::VPropHandleT, Mesh> pm_v_bool(mesh_, "pm_v_bool2"); + pm_v_bool.set_range(mesh_.vertices(), false); + for (int i = 0; i < 4; ++i) + ASSERT_FALSE(pm_v_bool[vhandle[i]]); + pm_v_bool.set_range(mesh_.vertices(), true); + for (int i = 0; i < 4; ++i) + ASSERT_TRUE(pm_v_bool[vhandle[i]]); + + OpenMesh::PropertyManager< + OpenMesh::EPropHandleT, Mesh> pm_e_bool(mesh_, "pm_e_bool2"); + pm_e_bool.set_range(mesh_.edges(), false); + for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end(); + e_it != f_end; ++e_it) + ASSERT_FALSE(pm_e_bool[*e_it]); + pm_e_bool.set_range(mesh_.edges(), true); + for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end(); + e_it != f_end; ++e_it) + ASSERT_TRUE(pm_e_bool[*e_it]); + + OpenMesh::PropertyManager< + OpenMesh::FPropHandleT, Mesh> pm_f_bool(mesh_, "pm_f_bool2"); + pm_f_bool.set_range(mesh_.faces(), false); + for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end(); + f_it != f_end; ++f_it) + ASSERT_FALSE(pm_f_bool[*f_it]); + pm_f_bool.set_range(mesh_.faces(), true); + for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end(); + f_it != f_end; ++f_it) + ASSERT_TRUE(pm_f_bool[*f_it]); + } +#endif } /* @@ -97,7 +137,7 @@ TEST_F(OpenMeshPropertyManager, set_range_bool) { * C++11 Specific Tests * ==================================================================== */ -#if _MSC_VER >= 1900 || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) +#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) template bool has_property(const Mesh& _mesh, const std::string& _name) { diff --git a/src/Unittests/unittests_vector_type.cc b/src/Unittests/unittests_vector_type.cc index 7c1dd5a1..ef86ccad 100644 --- a/src/Unittests/unittests_vector_type.cc +++ b/src/Unittests/unittests_vector_type.cc @@ -3,6 +3,10 @@ #include #include +#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) +#include +#endif + namespace { class OpenMeshVectorTest : public testing::Test { @@ -84,7 +88,7 @@ TEST_F(OpenMeshVectorTest, VectorCasting) { } -#if _MSC_VER >= 1900 || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) +#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) TEST_F(OpenMeshVectorTest, cpp11_constructors) { OpenMesh::Vec3d vec1 { 1.2, 2.0, 3.0 }; @@ -323,4 +327,76 @@ TEST_F(OpenMeshVectorTest, size_dim) { EXPECT_EQ(2, v2i.dim()); } +class OpenMeshVectorGCCBugTest; +void trigger_alignment_bug(OpenMeshVectorGCCBugTest &obj); + +/** + * This is a regression test for a GCC compiler bug. + * @see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66598 + * @see https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/issues/32 + */ +class OpenMeshVectorGCCBugTest : public testing::Test { + + protected: + + virtual void SetUp() { + /* + * WARNING: DO NOT CHANGE ANYTHGIN! Every single line, as + * pointless as it may look, is carefully crafted to provoke + * the GCC optimizer bug mentioned above. + */ + testfn = trigger_alignment_bug; + vec1 = OpenMesh::Vec4f(1.0f, 2.0f, 3.0f, 4.0f); + vec2 = OpenMesh::Vec4f(5.0f, 6.0f, 7.0f, 8.0f); + padding = 42; + } + + virtual void TearDown() { + // Do some final stuff with the member data here... + } + + public: + /* + * WARNING: DO NOT CHANGE ANYTHGIN! Every single line, as + * pointless as it may look, is carefully crafted to provoke + * the GCC optimizer bug mentioned above. + */ + int32_t padding; + OpenMesh::Vec4f vec1, vec2; + void (*testfn)(OpenMeshVectorGCCBugTest &obj); + + OpenMesh::Vec4f &get_vec1() { return vec1; } + OpenMesh::Vec4f &get_vec2() { return vec2; } +}; + +void trigger_alignment_bug(OpenMeshVectorGCCBugTest &obj) { + /* + * WARNING: DO NOT CHANGE ANYTHGIN! Every single line, as + * pointless as it may look, is carefully crafted to provoke + * the GCC optimizer bug mentioned above. + */ + int x1 = 1; + + OpenMesh::Vec4f vec3 = obj.get_vec1(); + OpenMesh::Vec4f vec4 = obj.get_vec2(); + vec3 += vec4; + + EXPECT_EQ(1, x1); + EXPECT_EQ(42, obj.padding); + EXPECT_EQ(6.0f, vec3[0]); + EXPECT_EQ(8.0f, vec3[1]); + EXPECT_EQ(10.0f, vec3[2]); + EXPECT_EQ(12.0f, vec3[3]); +} + +TEST_F(OpenMeshVectorGCCBugTest, alignment_bug) { + /* + * WARNING: DO NOT CHANGE ANYTHGIN! Every single line, as + * pointless as it may look, is carefully crafted to provoke + * the GCC optimizer bug mentioned above. + */ + (*testfn)(*this); +} + + }