Browse Source

"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 <cstring>, which is good.
vectorfields
Vladimír Vondruš 14 years ago
parent
commit
c8e33a74cc
  1. 66
      src/Math/Matrix.h
  2. 30
      src/Math/Matrix3.h
  3. 57
      src/Math/Matrix4.h
  4. 2
      src/Math/Test/MatrixTest.cpp
  5. 2
      src/Math/Test/VectorTest.cpp
  6. 55
      src/Math/Vector.h
  7. 23
      src/Math/Vector2.h
  8. 41
      src/Math/Vector3.h
  9. 43
      src/Math/Vector4.h
  10. 2
      src/MeshTools/Clean.h

66
src/Math/Matrix.h

@ -30,13 +30,29 @@ namespace Magnum { namespace Math {
*/
template<class T, size_t size> 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<T, size>& from(T* data) {
return *reinterpret_cast<Matrix<T, size>*>(data);
}
/** @copydoc from(T*) */
inline constexpr static const Matrix<T, size>& from(const T* data) {
return *reinterpret_cast<const Matrix<T, size>*>(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<T>(1);
}
@ -49,55 +65,32 @@ template<class T, size_t size> class Matrix {
* Note that the values are in column-major order.
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class ...U> inline Matrix(T first, U&&... next): _data{first, std::forward<U>(next)...} {}
template<class ...U> inline constexpr Matrix(T first, U&&... next): _data{first, std::forward<U>(next)...} {}
#else
template<class ...U> inline Matrix(T first, U&&... next);
template<class ...U> 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<T, size>& other) {
setData(other.data());
}
inline constexpr Matrix(const Matrix<T, size>& other) = default;
/** @brief Assignment operator */
inline Matrix<T, size>& operator=(const Matrix<T, size>& other) {
if(&other != this) setData(other.data());
return *this;
}
inline Matrix<T, size>& operator=(const Matrix<T, size>& 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<int, 5> 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<T, size> at(size_t col) const {
return _data+col*size;
inline constexpr Vector<T, size> at(size_t col) const {
return *reinterpret_cast<const Vector<T, size>*>(_data+col*size);
}
/** @brief Set value at given position */
@ -126,7 +119,7 @@ template<class T, size_t size> class Matrix {
}
/** @brief Non-equality operator */
inline bool operator!=(const Matrix<T, size>& other) const {
inline constexpr bool operator!=(const Matrix<T, size>& other) const {
return !operator==(other);
}
@ -226,8 +219,7 @@ template<class T, size_t size> class Matrix {
/* Barebone template specialization for 2x2 matrix (only for determinant computation) */
template<class T> class Matrix<T, 2> {
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));

30
src/Math/Matrix3.h

@ -27,8 +27,23 @@ namespace Magnum { namespace Math {
/** @brief 3x3 matrix */
template<class T> class Matrix3: public Matrix<T, 3> {
public:
/** @copydoc Matrix::from(T*) */
inline constexpr static Matrix3<T>& from(T* data) {
return *reinterpret_cast<Matrix3<T>*>(data);
}
/** @copydoc Matrix::from(const T*) */
inline constexpr static const Matrix3<T>& from(const T* data) {
return *reinterpret_cast<const Matrix3<T>*>(data);
}
/** @copydoc Matrix::Matrix(bool) */
inline Matrix3(bool identity = true): Matrix<T, 3>(identity) {}
inline constexpr Matrix3(bool identity = true): Matrix<T, 3>{
/** @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 T> class Matrix3: public Matrix<T, 3> {
* Note that the values are in column-major order.
*/
/* doxygen: @copydoc Matrix::Matrix(T, U&&...) doesn't work */
template<class ...U> inline Matrix3(T first, U&&... next): Matrix<T, 3>(first, std::forward<U>(next)...) {}
/** @copydoc Matrix::Matrix(const T*) */
inline Matrix3(const T* data): Matrix<T, 3>(data) {}
template<class ...U> inline constexpr Matrix3(T first, U&&... next): Matrix<T, 3>(first, std::forward<U>(next)...) {}
/** @copydoc Matrix::Matrix(const Matrix<T, size>&) */
inline Matrix3(const Matrix<T, 3>& other): Matrix<T, 3>(other) {}
inline constexpr Matrix3(const Matrix<T, 3>& other): Matrix<T, 3>(other) {}
/** @copydoc Matrix::operator=() */
inline Matrix3<T>& operator=(const Matrix<T, 3>& other) { return Matrix<T, 3>::operator=(other); }
inline constexpr Matrix3<T>& operator=(const Matrix<T, 3>& other) { return Matrix<T, 3>::operator=(other); }
/** @copydoc Matrix::at(size_t) const */
inline Vector3<T> at(size_t col) const { return Matrix<T, 3>::at(col); }
inline constexpr Vector3<T> at(size_t col) const { return Matrix<T, 3>::at(col); }
/** @copydoc Matrix::at(size_t, size_t) const */
inline T at(size_t row, size_t col) const { return Matrix<T, 3>::at(row, col); }
inline constexpr T at(size_t row, size_t col) const { return Matrix<T, 3>::at(row, col); }
/** @copydoc Matrix::operator*(const Matrix<T, size>&) const */
inline Matrix3<T> operator*(const Matrix<T, 3>& other) const { return Matrix<T, 3>::operator*(other); }

57
src/Math/Matrix4.h

@ -33,28 +33,40 @@ namespace Magnum { namespace Math {
*/
template<class T> class Matrix4: public Matrix<T, 4> {
public:
/** @copydoc Matrix::from(T*) */
inline constexpr static Matrix4<T>& from(T* data) {
return *reinterpret_cast<Matrix4<T>*>(data);
}
/** @copydoc Matrix::from(const T*) */
inline constexpr static const Matrix4<T>& from(const T* data) {
return *reinterpret_cast<const Matrix4<T>*>(data);
}
/**
* @brief Translation matrix
* @param vec Translation vector
*/
static Matrix4<T> translation(const Vector3<T>& 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<T> translation(const Vector3<T>& 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<T>& 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<T>& 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 T> class Matrix4: public Matrix<T, 4> {
}
/** @copydoc Matrix::Matrix(bool) */
inline Matrix4(bool identity = true): Matrix<T, 4>(identity) {}
inline constexpr Matrix4(bool identity = true): Matrix<T, 4>{
/** @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 T> class Matrix4: public Matrix<T, 4> {
* Note that the values are in column-major order.
*/
/* doxygen: @copydoc Matrix::Matrix(T, U&&...) doesn't work */
template<class ...U> inline Matrix4(T first, U&&... next): Matrix<T, 4>(first, std::forward<U>(next)...) {}
/** @copydoc Matrix::Matrix(const T*) */
inline Matrix4(const T* data): Matrix<T, 4>(data) {}
template<class ...U> inline constexpr Matrix4(T first, U&&... next): Matrix<T, 4>(first, std::forward<U>(next)...) {}
/** @copydoc Matrix::Matrix(const Matrix<T, size>&) */
inline Matrix4(const Matrix<T, 4>& other): Matrix<T, 4>(other) {}
inline constexpr Matrix4(const Matrix<T, 4>& other): Matrix<T, 4>(other) {}
/** @copydoc Matrix::operator=() */
inline Matrix4<T>& operator=(const Matrix<T, 4>& other) { return Matrix<T, 4>::operator=(other); }
inline constexpr Matrix4<T>& operator=(const Matrix<T, 4>& other) { return Matrix<T, 4>::operator=(other); }
/** @copydoc Matrix::at(size_t) const */
inline Vector4<T> at(size_t col) const { return Matrix<T, 4>::at(col); }
inline constexpr Vector4<T> at(size_t col) const { return Matrix<T, 4>::at(col); }
/** @copydoc Matrix::at(size_t, size_t) const */
inline T at(size_t row, size_t col) const { return Matrix<T, 4>::at(row, col); }
inline constexpr T at(size_t row, size_t col) const { return Matrix<T, 4>::at(row, col); }
/** @copydoc Matrix::operator*(const Matrix<T, size>&) const */
inline Matrix4<T> operator*(const Matrix<T, 4>& other) const { return Matrix<T, 4>::operator*(other); }

2
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() {

2
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() {

55
src/Math/Vector.h

@ -19,7 +19,6 @@
* @brief Class Magnum::Math::Vector
*/
#include <cstring>
#include <cmath>
#include "Utility/Debug.h"
@ -33,15 +32,30 @@ template<class T, size_t size> 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<T, size>& from(T* data) {
return *reinterpret_cast<Vector<T, size>*>(data);
}
/** @copydoc from(T*) */
inline constexpr static const Vector<T, size>& from(const T* data) {
return *reinterpret_cast<Vector<T, size>*>(data);
}
/** @brief Angle between vectors */
inline static T angle(const Vector<T, size>& a, const Vector<T, size>& 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 T, size_t size> class Vector {
* @param next Next values
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class ...U> inline Vector(T first, U&&... next): _data{first, std::forward<U>(next)...} {}
template<class ...U> inline constexpr Vector(T first, U&&... next): _data{first, std::forward<U>(next)...} {}
#else
template<class ...U> inline Vector(T first, U&&... next);
template<class ...U> 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<T, size>& other) {
setData(other.data());
}
inline constexpr Vector(const Vector<T, size>& other) = default;
/** @brief Assignment operator */
inline Vector<T, size>& operator=(const Vector<T, size>& other) {
if(&other != this) setData(other.data());
return *this;
}
inline Vector<T, size>& operator=(const Vector<T, size>& 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]; }

23
src/Math/Vector2.h

@ -26,24 +26,31 @@ namespace Magnum { namespace Math {
/** @brief Two-component vector */
template<class T> class Vector2: public Vector<T, 2> {
public:
/** @copydoc Vector::Vector */
inline Vector2() {}
/** @copydoc Vector::from(T*) */
inline constexpr static Vector2<T>& from(T* data) {
return *reinterpret_cast<Vector2<T>*>(data);
}
/** @copydoc Vector::Vector(const T*) */
inline Vector2(const T* data): Vector<T, 2>(data) {}
/** @copydoc Vector::from(const T*) */
inline constexpr static const Vector2<T>& from(const T* data) {
return *reinterpret_cast<const Vector2<T>*>(data);
}
/** @copydoc Vector::Vector */
inline constexpr Vector2() {}
/** @copydoc Vector::Vector(const Vector&) */
inline Vector2(const Vector<T, 2>& other): Vector<T, 2>(other) {}
inline constexpr Vector2(const Vector<T, 2>& other): Vector<T, 2>(other) {}
/**
* @brief Constructor
* @param x X value
* @param y Y value
*/
inline Vector2(T x, T y): Vector<T, 2>(x, y) {}
inline constexpr Vector2(T x, T y): Vector<T, 2>(x, y) {}
inline T x() const { return Vector<T, 2>::at(0); } /**< @brief X component */
inline T y() const { return Vector<T, 2>::at(1); } /**< @brief Y component */
inline constexpr T x() const { return Vector<T, 2>::at(0); } /**< @brief X component */
inline constexpr T y() const { return Vector<T, 2>::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 */

41
src/Math/Vector3.h

@ -26,30 +26,37 @@ namespace Magnum { namespace Math {
/** @brief Three-component vector */
template<class T> class Vector3: public Vector<T, 3> {
public:
/** @copydoc Vector::from(T*) */
inline constexpr static Vector3<T>& from(T* data) {
return *reinterpret_cast<Vector3<T>*>(data);
}
/** @copydoc Vector::from(const T*) */
inline constexpr static const Vector3<T>& from(const T* data) {
return *reinterpret_cast<const Vector3<T>*>(data);
}
/** @brief Vector in direction of X axis */
inline static Vector3<T> xAxis(T length = 1) { return Vector3<T>(length, 0, 0); }
inline constexpr static Vector3<T> xAxis(T length = 1) { return Vector3<T>(length, 0, 0); }
/** @brief Vector in direction of Y axis */
inline static Vector3<T> yAxis(T length = 1) { return Vector3<T>(0, length, 0); }
inline constexpr static Vector3<T> yAxis(T length = 1) { return Vector3<T>(0, length, 0); }
/** @brief Vector in direction of Z axis */
inline static Vector3<T> zAxis(T length = 1) { return Vector3<T>(0, 0, length); }
inline constexpr static Vector3<T> zAxis(T length = 1) { return Vector3<T>(0, 0, length); }
/** @brief Cross product */
static Vector3<T> cross(const Vector3<T>& a, const Vector3<T>& b) {
constexpr static Vector3<T> cross(const Vector3<T>& a, const Vector3<T>& b) {
return Vector3<T>(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<T, 3>(data) {}
inline constexpr Vector3() {}
/** @copydoc Vector::Vector(const Vector&) */
inline Vector3(const Vector<T, 3>& other): Vector<T, 3>(other) {}
inline constexpr Vector3(const Vector<T, 3>& other): Vector<T, 3>(other) {}
/**
* @brief Constructor
@ -57,26 +64,26 @@ template<class T> class Vector3: public Vector<T, 3> {
* @param y Y / G value
* @param z Z / B value
*/
inline Vector3(T x, T y, T z): Vector<T, 3>(x, y, z) {}
inline constexpr Vector3(T x, T y, T z): Vector<T, 3>(x, y, z) {}
/**
* @brief Constructor
* @param other Two component vector
* @param z Z / B value
*/
inline Vector3(const Vector<T, 2>& other, T z = T(0)): Vector<T, 3>(other[0], other[1], z) {}
inline constexpr Vector3(const Vector<T, 2>& other, T z = T(0)): Vector<T, 3>(other[0], other[1], z) {}
inline T x() const { return Vector<T, 3>::at(0); } /**< @brief X component */
inline T y() const { return Vector<T, 3>::at(1); } /**< @brief Y component */
inline T z() const { return Vector<T, 3>::at(2); } /**< @brief Z component */
inline constexpr T x() const { return Vector<T, 3>::at(0); } /**< @brief X component */
inline constexpr T y() const { return Vector<T, 3>::at(1); } /**< @brief Y component */
inline constexpr T z() const { return Vector<T, 3>::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 */

43
src/Math/Vector4.h

@ -26,20 +26,25 @@ namespace Magnum { namespace Math {
/** @brief Four-component vector */
template<class T> class Vector4: public Vector<T, 4> {
public:
/** @copydoc Vector::from(T*) */
inline constexpr static Vector4<T>& from(T* data) {
return *reinterpret_cast<Vector4<T>*>(data);
}
/** @copydoc Vector::from(const T*) */
inline constexpr static const Vector4<T>& from(const T* data) {
return *reinterpret_cast<const Vector4<T>*>(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<T, 4>(data) {}
inline constexpr Vector4(): Vector<T, 4>(T(0), T(0), T(0), T(1)) {}
/** @copydoc Vector::Vector(const Vector&) */
inline Vector4(const Vector<T, 4>& other): Vector<T, 4>(other) {}
inline constexpr Vector4(const Vector<T, 4>& other): Vector<T, 4>(other) {}
/**
* @brief Constructor
@ -48,19 +53,19 @@ template<class T> class Vector4: public Vector<T, 4> {
* @param z Z / B value
* @param w W / A value
*/
inline Vector4(T x, T y, T z, T w = T(1)): Vector<T, 4>(x, y, z, w) {}
inline constexpr Vector4(T x, T y, T z, T w = T(1)): Vector<T, 4>(x, y, z, w) {}
/**
* @brief Constructor
* @param other Three component vector
* @param w W / A value
*/
inline Vector4(const Vector<T, 3>& other, T w = T(1)): Vector<T, 4>(other[0], other[1], other[2], w) {}
inline constexpr Vector4(const Vector<T, 3>& other, T w = T(1)): Vector<T, 4>(other[0], other[1], other[2], w) {}
inline T x() const { return Vector<T, 4>::at(0); } /**< @brief X component */
inline T y() const { return Vector<T, 4>::at(1); } /**< @brief Y component */
inline T z() const { return Vector<T, 4>::at(2); } /**< @brief Z component */
inline T w() const { return Vector<T, 4>::at(3); } /**< @brief W component */
inline constexpr T x() const { return Vector<T, 4>::at(0); } /**< @brief X component */
inline constexpr T y() const { return Vector<T, 4>::at(1); } /**< @brief Y component */
inline constexpr T z() const { return Vector<T, 4>::at(2); } /**< @brief Z component */
inline constexpr T w() const { return Vector<T, 4>::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 T> class Vector4: public Vector<T, 4> {
* @brief XYZ part of the vector
* @return First three components of the vector
*/
inline Vector3<T> xyz() const { return Vector3<T>(Vector<T, 4>::data()); }
inline constexpr Vector3<T> xyz() const { return Vector3<T>::from(Vector<T, 4>::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 T> class Vector4: public Vector<T, 4> {
* @brief RGB part of the vector
* @return First three components of the vector
*/
inline Vector3<T> rgb() const { return xyz(); }
inline constexpr Vector3<T> rgb() const { return xyz(); }
/** @copydoc Vector::operator=() */
inline Vector4<T>& operator=(const Vector<T, 4>& other) { return Vector<T, 4>::operator=(other); }

2
src/MeshTools/Clean.h

@ -92,7 +92,7 @@ template<class Vertex, size_t vertexSize = Vertex::Size> class Clean {
exists, change vertex pointer of the face to already
existing vertex */
HashedVertex v(*it, table.size());
auto result = table.insert(std::pair<Math::Vector<size_t, vertexSize>, HashedVertex>(index, v));
auto result = table.insert(std::pair<Math::Vector<size_t, vertexSize>, HashedVertex>(Math::Vector<size_t, vertexSize>::from(index), v));
*it = result.first->second.newIndex;
}

Loading…
Cancel
Save