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; }