From c8e33a74cc9c40225b60b81f063c3047e64715d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 10 Mar 2012 01:01:21 +0100 Subject: [PATCH] "constexpr"-ized Matrix and Vector classes. It should improve performance, because what can be computed at compile time is now computed at compile time. In addition these things have been changed or improved: * Removed constructors from T*, as they cannot be AFAIK written using constexpr functions only and they only do unnecessary data copying most of the time. The functionality is now provided using static functions Matrix*::from() and Vector*::from() which returns either const or non-const reference to original data, so no copy is performed. These functions also have explicit warning about unsafe operations. * Defaulted copy constructors and assignment operators, using "default initialization" for arrays instead of memsetting it with zeros. It should behave the same and this way we don't need any memcpy(), memset() etc. from , which is good. --- src/Math/Matrix.h | 66 ++++++++++++++++-------------------- src/Math/Matrix3.h | 30 +++++++++++----- src/Math/Matrix4.h | 57 +++++++++++++++++++------------ src/Math/Test/MatrixTest.cpp | 2 +- src/Math/Test/VectorTest.cpp | 2 +- src/Math/Vector.h | 55 ++++++++++++++---------------- src/Math/Vector2.h | 23 ++++++++----- src/Math/Vector3.h | 41 ++++++++++++---------- src/Math/Vector4.h | 43 ++++++++++++----------- src/MeshTools/Clean.h | 2 +- 10 files changed, 177 insertions(+), 144 deletions(-) diff --git a/src/Math/Matrix.h b/src/Math/Matrix.h index af1066b99..55916127b 100644 --- a/src/Math/Matrix.h +++ b/src/Math/Matrix.h @@ -30,13 +30,29 @@ namespace Magnum { namespace Math { */ template class Matrix { public: + /** + * @brief %Matrix from array + * @return Reference to the data as if it was Matrix, thus doesn't + * perform any copying. + * + * @attention Use with caution, the function doesn't check whether the + * array is long enough. + */ + inline constexpr static Matrix& from(T* data) { + return *reinterpret_cast*>(data); + } + + /** @copydoc from(T*) */ + inline constexpr static const Matrix& from(const T* data) { + return *reinterpret_cast*>(data); + } + /** * @brief Default constructor * @param identity Create identity matrix instead of zero matrix. */ - inline Matrix(bool identity = true) { - memset(_data, 0, size*size*sizeof(T)); - + inline Matrix(bool identity = true): _data() { + /** @todo constexpr how? */ if(identity) for(size_t i = 0; i != size; ++i) _data[size*i+i] = static_cast(1); } @@ -49,55 +65,32 @@ template class Matrix { * Note that the values are in column-major order. */ #ifndef DOXYGEN_GENERATING_OUTPUT - template inline Matrix(T first, U&&... next): _data{first, std::forward(next)...} {} + template inline constexpr Matrix(T first, U&&... next): _data{first, std::forward(next)...} {} #else - template inline Matrix(T first, U&&... next); + template inline constexpr Matrix(T first, U&&... next); #endif - /** - * @brief Constructor - * @param data One-dimensional array of `size*size` length in - * column-major order. - */ - inline Matrix(const T* data) { setData(data); } - /** @brief Copy constructor */ - inline Matrix(const Matrix& other) { - setData(other.data()); - } + inline constexpr Matrix(const Matrix& other) = default; /** @brief Assignment operator */ - inline Matrix& operator=(const Matrix& other) { - if(&other != this) setData(other.data()); - return *this; - } + inline Matrix& operator=(const Matrix& other) = default; /** * @brief Raw data * @return One-dimensional array of `size*size` length in column-major * order. */ - inline const T* data() const { return _data; } - - /** - * @brief Set raw data - * @param data One-dimensional array of `size*size` length in - * column-major order. - * - * @bug Creating Matrix from float* ?? - */ - inline void setData(const T* data) { - memcpy(_data, data, size*size*sizeof(T)); - } + inline constexpr const T* data() const { return _data; } /** @brief Value at given position */ - inline T at(size_t row, size_t col) const { + inline constexpr T at(size_t row, size_t col) const { return _data[col*size+row]; } /** @brief %Matrix column */ - inline Vector at(size_t col) const { - return _data+col*size; + inline constexpr Vector at(size_t col) const { + return *reinterpret_cast*>(_data+col*size); } /** @brief Set value at given position */ @@ -126,7 +119,7 @@ template class Matrix { } /** @brief Non-equality operator */ - inline bool operator!=(const Matrix& other) const { + inline constexpr bool operator!=(const Matrix& other) const { return !operator==(other); } @@ -226,8 +219,7 @@ template class Matrix { /* Barebone template specialization for 2x2 matrix (only for determinant computation) */ template class Matrix { public: - inline Matrix(bool identity = true) { - memset(_data, 0, 4*sizeof(T)); + inline Matrix(bool identity = true): _data() { if(identity) { set(0, 0, T(1)); set(1, 1, T(1)); diff --git a/src/Math/Matrix3.h b/src/Math/Matrix3.h index 90d36471e..d810fa6cf 100644 --- a/src/Math/Matrix3.h +++ b/src/Math/Matrix3.h @@ -27,8 +27,23 @@ namespace Magnum { namespace Math { /** @brief 3x3 matrix */ template class Matrix3: public Matrix { public: + /** @copydoc Matrix::from(T*) */ + inline constexpr static Matrix3& from(T* data) { + return *reinterpret_cast*>(data); + } + + /** @copydoc Matrix::from(const T*) */ + inline constexpr static const Matrix3& from(const T* data) { + return *reinterpret_cast*>(data); + } + /** @copydoc Matrix::Matrix(bool) */ - inline Matrix3(bool identity = true): Matrix(identity) {} + inline constexpr Matrix3(bool identity = true): Matrix{ + /** @todo Make this in Matrix itself, after it will be constexpr */ + identity ? 1.0f : 0.0f, 0.0f, 0.0f, + 0.0f, identity ? 1.0f : 0.0f, 0.0f, + 0.0f, 0.0f, identity ? 1.0f : 0.0f + } {} /** * @brief Initializer-list constructor @@ -38,22 +53,19 @@ template class Matrix3: public Matrix { * Note that the values are in column-major order. */ /* doxygen: @copydoc Matrix::Matrix(T, U&&...) doesn't work */ - template inline Matrix3(T first, U&&... next): Matrix(first, std::forward(next)...) {} - - /** @copydoc Matrix::Matrix(const T*) */ - inline Matrix3(const T* data): Matrix(data) {} + template inline constexpr Matrix3(T first, U&&... next): Matrix(first, std::forward(next)...) {} /** @copydoc Matrix::Matrix(const Matrix&) */ - inline Matrix3(const Matrix& other): Matrix(other) {} + inline constexpr Matrix3(const Matrix& other): Matrix(other) {} /** @copydoc Matrix::operator=() */ - inline Matrix3& operator=(const Matrix& other) { return Matrix::operator=(other); } + inline constexpr Matrix3& operator=(const Matrix& other) { return Matrix::operator=(other); } /** @copydoc Matrix::at(size_t) const */ - inline Vector3 at(size_t col) const { return Matrix::at(col); } + inline constexpr Vector3 at(size_t col) const { return Matrix::at(col); } /** @copydoc Matrix::at(size_t, size_t) const */ - inline T at(size_t row, size_t col) const { return Matrix::at(row, col); } + inline constexpr T at(size_t row, size_t col) const { return Matrix::at(row, col); } /** @copydoc Matrix::operator*(const Matrix&) const */ inline Matrix3 operator*(const Matrix& other) const { return Matrix::operator*(other); } diff --git a/src/Math/Matrix4.h b/src/Math/Matrix4.h index 8699336d1..3c813d85c 100644 --- a/src/Math/Matrix4.h +++ b/src/Math/Matrix4.h @@ -33,28 +33,40 @@ namespace Magnum { namespace Math { */ template class Matrix4: public Matrix { public: + /** @copydoc Matrix::from(T*) */ + inline constexpr static Matrix4& from(T* data) { + return *reinterpret_cast*>(data); + } + + /** @copydoc Matrix::from(const T*) */ + inline constexpr static const Matrix4& from(const T* data) { + return *reinterpret_cast*>(data); + } + /** * @brief Translation matrix * @param vec Translation vector */ - static Matrix4 translation(const Vector3& vec) { - Matrix4 out; /* (Identity matrix) */ - out.set(0, 3, vec.x()); - out.set(1, 3, vec.y()); - out.set(2, 3, vec.z()); - return out; + static constexpr Matrix4 translation(const Vector3& vec) { + return Matrix4( /* Column-major! */ + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + vec.x(), vec.y(), vec.z(), 1.0f + ); } /** * @brief Scaling matrix * @param vec Scaling vector */ - static Matrix4 scaling(const Vector3& vec) { - Matrix4 out; /* (Identity matrix) */ - out.set(0, 0, vec.x()); - out.set(1, 1, vec.y()); - out.set(2, 2, vec.z()); - return out; + static constexpr Matrix4 scaling(const Vector3& vec) { + return Matrix4( /* Column-major! */ + vec.x(), 0.0f, 0.0f, 0.0f, + 0.0f, vec.y(), 0.0f, 0.0f, + 0.0f, 0.0f, vec.z(), 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); } /** @@ -94,7 +106,13 @@ template class Matrix4: public Matrix { } /** @copydoc Matrix::Matrix(bool) */ - inline Matrix4(bool identity = true): Matrix(identity) {} + inline constexpr Matrix4(bool identity = true): Matrix{ + /** @todo Make this in Matrix itself, after it will be constexpr */ + identity ? 1.0f : 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, identity ? 1.0f : 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, identity ? 1.0f : 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, identity ? 1.0f : 0.0f + } {} /** * @brief Initializer-list constructor @@ -104,22 +122,19 @@ template class Matrix4: public Matrix { * Note that the values are in column-major order. */ /* doxygen: @copydoc Matrix::Matrix(T, U&&...) doesn't work */ - template inline Matrix4(T first, U&&... next): Matrix(first, std::forward(next)...) {} - - /** @copydoc Matrix::Matrix(const T*) */ - inline Matrix4(const T* data): Matrix(data) {} + template inline constexpr Matrix4(T first, U&&... next): Matrix(first, std::forward(next)...) {} /** @copydoc Matrix::Matrix(const Matrix&) */ - inline Matrix4(const Matrix& other): Matrix(other) {} + inline constexpr Matrix4(const Matrix& other): Matrix(other) {} /** @copydoc Matrix::operator=() */ - inline Matrix4& operator=(const Matrix& other) { return Matrix::operator=(other); } + inline constexpr Matrix4& operator=(const Matrix& other) { return Matrix::operator=(other); } /** @copydoc Matrix::at(size_t) const */ - inline Vector4 at(size_t col) const { return Matrix::at(col); } + inline constexpr Vector4 at(size_t col) const { return Matrix::at(col); } /** @copydoc Matrix::at(size_t, size_t) const */ - inline T at(size_t row, size_t col) const { return Matrix::at(row, col); } + inline constexpr T at(size_t row, size_t col) const { return Matrix::at(row, col); } /** @copydoc Matrix::operator*(const Matrix&) const */ inline Matrix4 operator*(const Matrix& other) const { return Matrix::operator*(other); } diff --git a/src/Math/Test/MatrixTest.cpp b/src/Math/Test/MatrixTest.cpp index da467fe47..20d38c5da 100644 --- a/src/Math/Test/MatrixTest.cpp +++ b/src/Math/Test/MatrixTest.cpp @@ -46,7 +46,7 @@ void MatrixTest::construct() { 9.0f, 4.0f, 5.0f, 9.0f ); - QVERIFY(Matrix4(m) == expected); + QVERIFY(Matrix4::from(m) == expected); } void MatrixTest::constructIdentity() { diff --git a/src/Math/Test/VectorTest.cpp b/src/Math/Test/VectorTest.cpp index 28e75a768..bb9e98de4 100644 --- a/src/Math/Test/VectorTest.cpp +++ b/src/Math/Test/VectorTest.cpp @@ -35,7 +35,7 @@ void VectorTest::construct() { QVERIFY((Vector4() == Vector4(0.0f, 0.0f, 0.0f, 0.0f))); float data[] = { 1.0f, 2.0f, 3.0f, 4.0f }; - QVERIFY((Vector4(data) == Vector4(1.0f, 2.0f, 3.0f, 4.0f))); + QVERIFY((Vector4::from(data) == Vector4(1.0f, 2.0f, 3.0f, 4.0f))); } void VectorTest::data() { diff --git a/src/Math/Vector.h b/src/Math/Vector.h index 1a9f152fd..2de8b96d6 100644 --- a/src/Math/Vector.h +++ b/src/Math/Vector.h @@ -19,7 +19,6 @@ * @brief Class Magnum::Math::Vector */ -#include #include #include "Utility/Debug.h" @@ -33,15 +32,30 @@ template class Vector { typedef T Type; /**< @brief %Vector data type */ const static size_t Size = size; /**< @brief %Vector size */ + /** + * @brief Vector from array + * @return Reference to the data as if it was Vector, thus doesn't + * perform any copying. + * + * @attention Use with caution, the function doesn't check whether the + * array is long enough. + */ + inline constexpr static Vector& from(T* data) { + return *reinterpret_cast*>(data); + } + + /** @copydoc from(T*) */ + inline constexpr static const Vector& from(const T* data) { + return *reinterpret_cast*>(data); + } + /** @brief Angle between vectors */ inline static T angle(const Vector& a, const Vector& b) { return acos((a*b)/(a.length()*b.length())); } /** @brief Default constructor */ - inline Vector() { - memset(_data, 0, size*sizeof(T)); - }; + inline constexpr Vector(): _data() {} /** * @brief Initializer-list constructor @@ -49,47 +63,28 @@ template class Vector { * @param next Next values */ #ifndef DOXYGEN_GENERATING_OUTPUT - template inline Vector(T first, U&&... next): _data{first, std::forward(next)...} {} + template inline constexpr Vector(T first, U&&... next): _data{first, std::forward(next)...} {} #else - template inline Vector(T first, U&&... next); + template inline constexpr Vector(T first, U&&... next); #endif - /** - * @brief Constructor - * @param data Array with the same size as the vector. - */ - inline Vector(const T* data) { setData(data); } - /** @brief Copy constructor */ - inline Vector(const Vector& other) { - setData(other.data()); - } + inline constexpr Vector(const Vector& other) = default; /** @brief Assignment operator */ - inline Vector& operator=(const Vector& other) { - if(&other != this) setData(other.data()); - return *this; - } + inline Vector& operator=(const Vector& other) = default; /** * @brief Raw data * @return Array with the same size as the vector */ - inline const T* data() const { return _data; } - - /** - * @brief Set raw data - * @param data Array with the same size as the vector - */ - inline void setData(const T* data) { - memcpy(_data, data, size*sizeof(T)); - } + inline constexpr const T* data() const { return _data; } /** @brief Value at given position */ - inline T at(size_t pos) const { return _data[pos]; } + inline constexpr T at(size_t pos) const { return _data[pos]; } /** @brief Value at given position */ - inline T operator[](size_t pos) const { return _data[pos]; } + inline constexpr T operator[](size_t pos) const { return _data[pos]; } /** @brief Reference to value at given position */ inline T& operator[](size_t pos) { return _data[pos]; } diff --git a/src/Math/Vector2.h b/src/Math/Vector2.h index 8d48ea289..c99c4083c 100644 --- a/src/Math/Vector2.h +++ b/src/Math/Vector2.h @@ -26,24 +26,31 @@ namespace Magnum { namespace Math { /** @brief Two-component vector */ template class Vector2: public Vector { public: - /** @copydoc Vector::Vector */ - inline Vector2() {} + /** @copydoc Vector::from(T*) */ + inline constexpr static Vector2& from(T* data) { + return *reinterpret_cast*>(data); + } - /** @copydoc Vector::Vector(const T*) */ - inline Vector2(const T* data): Vector(data) {} + /** @copydoc Vector::from(const T*) */ + inline constexpr static const Vector2& from(const T* data) { + return *reinterpret_cast*>(data); + } + + /** @copydoc Vector::Vector */ + inline constexpr Vector2() {} /** @copydoc Vector::Vector(const Vector&) */ - inline Vector2(const Vector& other): Vector(other) {} + inline constexpr Vector2(const Vector& other): Vector(other) {} /** * @brief Constructor * @param x X value * @param y Y value */ - inline Vector2(T x, T y): Vector(x, y) {} + inline constexpr Vector2(T x, T y): Vector(x, y) {} - inline T x() const { return Vector::at(0); } /**< @brief X component */ - inline T y() const { return Vector::at(1); } /**< @brief Y component */ + inline constexpr T x() const { return Vector::at(0); } /**< @brief X component */ + inline constexpr T y() const { return Vector::at(1); } /**< @brief Y component */ inline void setX(T value) { this->set(0, value); } /**< @brief Set X component */ inline void setY(T value) { this->set(1, value); } /**< @brief Set Y component */ diff --git a/src/Math/Vector3.h b/src/Math/Vector3.h index 59d040e8f..61aa55770 100644 --- a/src/Math/Vector3.h +++ b/src/Math/Vector3.h @@ -26,30 +26,37 @@ namespace Magnum { namespace Math { /** @brief Three-component vector */ template class Vector3: public Vector { public: + /** @copydoc Vector::from(T*) */ + inline constexpr static Vector3& from(T* data) { + return *reinterpret_cast*>(data); + } + + /** @copydoc Vector::from(const T*) */ + inline constexpr static const Vector3& from(const T* data) { + return *reinterpret_cast*>(data); + } + /** @brief Vector in direction of X axis */ - inline static Vector3 xAxis(T length = 1) { return Vector3(length, 0, 0); } + inline constexpr static Vector3 xAxis(T length = 1) { return Vector3(length, 0, 0); } /** @brief Vector in direction of Y axis */ - inline static Vector3 yAxis(T length = 1) { return Vector3(0, length, 0); } + inline constexpr static Vector3 yAxis(T length = 1) { return Vector3(0, length, 0); } /** @brief Vector in direction of Z axis */ - inline static Vector3 zAxis(T length = 1) { return Vector3(0, 0, length); } + inline constexpr static Vector3 zAxis(T length = 1) { return Vector3(0, 0, length); } /** @brief Cross product */ - static Vector3 cross(const Vector3& a, const Vector3& b) { + constexpr static Vector3 cross(const Vector3& a, const Vector3& b) { return Vector3(a[1]*b[2]-a[2]*b[1], a[2]*b[0]-a[0]*b[2], a[0]*b[1]-a[1]*b[0]); } /** @copydoc Vector::Vector */ - inline Vector3() {} - - /** @copydoc Vector::Vector(const T*) */ - inline Vector3(const T* data): Vector(data) {} + inline constexpr Vector3() {} /** @copydoc Vector::Vector(const Vector&) */ - inline Vector3(const Vector& other): Vector(other) {} + inline constexpr Vector3(const Vector& other): Vector(other) {} /** * @brief Constructor @@ -57,26 +64,26 @@ template class Vector3: public Vector { * @param y Y / G value * @param z Z / B value */ - inline Vector3(T x, T y, T z): Vector(x, y, z) {} + inline constexpr Vector3(T x, T y, T z): Vector(x, y, z) {} /** * @brief Constructor * @param other Two component vector * @param z Z / B value */ - inline Vector3(const Vector& other, T z = T(0)): Vector(other[0], other[1], z) {} + inline constexpr Vector3(const Vector& other, T z = T(0)): Vector(other[0], other[1], z) {} - inline T x() const { return Vector::at(0); } /**< @brief X component */ - inline T y() const { return Vector::at(1); } /**< @brief Y component */ - inline T z() const { return Vector::at(2); } /**< @brief Z component */ + inline constexpr T x() const { return Vector::at(0); } /**< @brief X component */ + inline constexpr T y() const { return Vector::at(1); } /**< @brief Y component */ + inline constexpr T z() const { return Vector::at(2); } /**< @brief Z component */ inline void setX(T value) { this->set(0, value); } /**< @brief Set X component */ inline void setY(T value) { this->set(1, value); } /**< @brief Set Y component */ inline void setZ(T value) { this->set(2, value); } /**< @brief Set Z component */ - inline T r() const { return x(); } /**< @brief R component */ - inline T g() const { return x(); } /**< @brief G component */ - inline T b() const { return z(); } /**< @brief B component */ + inline constexpr T r() const { return x(); } /**< @brief R component */ + inline constexpr T g() const { return x(); } /**< @brief G component */ + inline constexpr T b() const { return z(); } /**< @brief B component */ inline void setR(T value) { setX(value); } /**< @brief Set R component */ inline void setG(T value) { setY(value); } /**< @brief Set G component */ diff --git a/src/Math/Vector4.h b/src/Math/Vector4.h index 3ba586d2d..48491bcec 100644 --- a/src/Math/Vector4.h +++ b/src/Math/Vector4.h @@ -26,20 +26,25 @@ namespace Magnum { namespace Math { /** @brief Four-component vector */ template class Vector4: public Vector { public: + /** @copydoc Vector::from(T*) */ + inline constexpr static Vector4& from(T* data) { + return *reinterpret_cast*>(data); + } + + /** @copydoc Vector::from(const T*) */ + inline constexpr static const Vector4& from(const T* data) { + return *reinterpret_cast*>(data); + } + /** * @copydoc Vector::Vector * * W / A component is set to one. */ - inline Vector4() { - setW(T(1)); - } - - /** @copydoc Vector::Vector(const T*) */ - inline Vector4(const T* data): Vector(data) {} + inline constexpr Vector4(): Vector(T(0), T(0), T(0), T(1)) {} /** @copydoc Vector::Vector(const Vector&) */ - inline Vector4(const Vector& other): Vector(other) {} + inline constexpr Vector4(const Vector& other): Vector(other) {} /** * @brief Constructor @@ -48,19 +53,19 @@ template class Vector4: public Vector { * @param z Z / B value * @param w W / A value */ - inline Vector4(T x, T y, T z, T w = T(1)): Vector(x, y, z, w) {} + inline constexpr Vector4(T x, T y, T z, T w = T(1)): Vector(x, y, z, w) {} /** * @brief Constructor * @param other Three component vector * @param w W / A value */ - inline Vector4(const Vector& other, T w = T(1)): Vector(other[0], other[1], other[2], w) {} + inline constexpr Vector4(const Vector& other, T w = T(1)): Vector(other[0], other[1], other[2], w) {} - inline T x() const { return Vector::at(0); } /**< @brief X component */ - inline T y() const { return Vector::at(1); } /**< @brief Y component */ - inline T z() const { return Vector::at(2); } /**< @brief Z component */ - inline T w() const { return Vector::at(3); } /**< @brief W component */ + inline constexpr T x() const { return Vector::at(0); } /**< @brief X component */ + inline constexpr T y() const { return Vector::at(1); } /**< @brief Y component */ + inline constexpr T z() const { return Vector::at(2); } /**< @brief Z component */ + inline constexpr T w() const { return Vector::at(3); } /**< @brief W component */ inline void setX(T value) { this->set(0, value); } /**< @brief Set X component */ inline void setY(T value) { this->set(1, value); } /**< @brief Set Y component */ @@ -71,12 +76,12 @@ template class Vector4: public Vector { * @brief XYZ part of the vector * @return First three components of the vector */ - inline Vector3 xyz() const { return Vector3(Vector::data()); } + inline constexpr Vector3 xyz() const { return Vector3::from(Vector::data()); } - inline T r() const { return x(); } /**< @brief R component */ - inline T g() const { return y(); } /**< @brief G component */ - inline T b() const { return z(); } /**< @brief B component */ - inline T a() const { return w(); } /**< @brief A component */ + inline constexpr T r() const { return x(); } /**< @brief R component */ + inline constexpr T g() const { return y(); } /**< @brief G component */ + inline constexpr T b() const { return z(); } /**< @brief B component */ + inline constexpr T a() const { return w(); } /**< @brief A component */ inline void setR(T value) { setX(value); } /**< @brief Set R component */ inline void setG(T value) { setY(value); } /**< @brief Set G component */ @@ -87,7 +92,7 @@ template class Vector4: public Vector { * @brief RGB part of the vector * @return First three components of the vector */ - inline Vector3 rgb() const { return xyz(); } + inline constexpr Vector3 rgb() const { return xyz(); } /** @copydoc Vector::operator=() */ inline Vector4& operator=(const Vector& other) { return Vector::operator=(other); } diff --git a/src/MeshTools/Clean.h b/src/MeshTools/Clean.h index 7f291d3e0..e9015be74 100644 --- a/src/MeshTools/Clean.h +++ b/src/MeshTools/Clean.h @@ -92,7 +92,7 @@ template class Clean { exists, change vertex pointer of the face to already existing vertex */ HashedVertex v(*it, table.size()); - auto result = table.insert(std::pair, HashedVertex>(index, v)); + auto result = table.insert(std::pair, HashedVertex>(Math::Vector::from(index), v)); *it = result.first->second.newIndex; }