@@ -43,7 +43,7 @@ liblolcore_headers = \ | |||||
lol/math/all.h \ | lol/math/all.h \ | ||||
lol/math/functions.h lol/math/vector.h lol/math/half.h lol/math/real.h \ | lol/math/functions.h lol/math/vector.h lol/math/half.h lol/math/real.h \ | ||||
lol/math/geometry.h lol/math/interp.h lol/math/rand.h lol/math/array2d.h \ | lol/math/geometry.h lol/math/interp.h lol/math/rand.h lol/math/array2d.h \ | ||||
lol/math/array3d.h lol/math/constants.h lol/math/matrix.h \ | |||||
lol/math/array3d.h lol/math/constants.h lol/math/matrix.h lol/math/ops.h \ | |||||
lol/math/transform.h \ | lol/math/transform.h \ | ||||
\ | \ | ||||
lol/algorithm/all.h \ | lol/algorithm/all.h \ | ||||
@@ -15,6 +15,7 @@ | |||||
#include <lol/math/functions.h> | #include <lol/math/functions.h> | ||||
#include <lol/math/half.h> | #include <lol/math/half.h> | ||||
#include <lol/math/real.h> | #include <lol/math/real.h> | ||||
#include <lol/math/ops.h> | |||||
#include <lol/math/vector.h> | #include <lol/math/vector.h> | ||||
#include <lol/math/matrix.h> | #include <lol/math/matrix.h> | ||||
#include <lol/math/transform.h> | #include <lol/math/transform.h> | ||||
@@ -116,6 +116,8 @@ public: | |||||
uint16_t bits; | uint16_t bits; | ||||
}; | }; | ||||
static_assert(sizeof(half) == 2, "sizeof(half) == 2"); | |||||
static inline half min(half a, half b) { return a < b ? a : b; } | static inline half min(half a, half b) { return a < b ? a : b; } | ||||
static inline half max(half a, half b) { return a > b ? a : b; } | static inline half max(half a, half b) { return a > b ? a : b; } | ||||
static inline float fmod(half a, half b) | static inline float fmod(half a, half b) | ||||
@@ -33,8 +33,11 @@ namespace lol | |||||
*/ | */ | ||||
template<typename T, int COLS, int ROWS> | template<typename T, int COLS, int ROWS> | ||||
struct mat_t : public linear_ops::base | |||||
struct mat_t | |||||
: public linear_ops::base<vec_t<T,ROWS>> | |||||
{ | { | ||||
static int const count = COLS; | |||||
typedef vec_t<T,ROWS> element; | |||||
typedef mat_t<T,COLS,ROWS> type; | typedef mat_t<T,COLS,ROWS> type; | ||||
inline mat_t() {} | inline mat_t() {} | ||||
@@ -59,8 +62,11 @@ private: | |||||
*/ | */ | ||||
template <typename T> | template <typename T> | ||||
struct mat_t<T, 2, 2> : public linear_ops::base | |||||
struct mat_t<T, 2, 2> | |||||
: public linear_ops::base<vec_t<T,2>> | |||||
{ | { | ||||
static int const count = 2; | |||||
typedef vec_t<T,2> element; | |||||
typedef mat_t<T,2,2> type; | typedef mat_t<T,2,2> type; | ||||
inline mat_t() {} | inline mat_t() {} | ||||
@@ -119,13 +125,25 @@ private: | |||||
#endif | #endif | ||||
}; | }; | ||||
static_assert(sizeof(i8mat2) == 4, "sizeof(i8mat2) == 4"); | |||||
static_assert(sizeof(i16mat2) == 8, "sizeof(i16mat2) == 8"); | |||||
static_assert(sizeof(imat2) == 16, "sizeof(imat2) == 16"); | |||||
static_assert(sizeof(i64mat2) == 32, "sizeof(i64mat2) == 32"); | |||||
static_assert(sizeof(f16mat2) == 8, "sizeof(f16mat2) == 8"); | |||||
static_assert(sizeof(mat2) == 16, "sizeof(mat2) == 16"); | |||||
static_assert(sizeof(dmat2) == 32, "sizeof(dmat2) == 32"); | |||||
/* | /* | ||||
* 3×3-element matrices | * 3×3-element matrices | ||||
*/ | */ | ||||
template <typename T> | template <typename T> | ||||
struct mat_t<T, 3, 3> : public linear_ops::base | |||||
struct mat_t<T, 3, 3> | |||||
: public linear_ops::base<vec_t<T,3>> | |||||
{ | { | ||||
static int const count = 3; | |||||
typedef vec_t<T,3> element; | |||||
typedef mat_t<T,3,3> type; | typedef mat_t<T,3,3> type; | ||||
inline mat_t() {} | inline mat_t() {} | ||||
@@ -230,13 +248,25 @@ private: | |||||
#endif | #endif | ||||
}; | }; | ||||
static_assert(sizeof(i8mat3) == 9, "sizeof(i8mat3) == 9"); | |||||
static_assert(sizeof(i16mat3) == 18, "sizeof(i16mat3) == 18"); | |||||
static_assert(sizeof(imat3) == 36, "sizeof(imat3) == 36"); | |||||
static_assert(sizeof(i64mat3) == 72, "sizeof(i64mat3) == 72"); | |||||
static_assert(sizeof(f16mat3) == 18, "sizeof(f16mat3) == 18"); | |||||
static_assert(sizeof(mat3) == 36, "sizeof(mat3) == 36"); | |||||
static_assert(sizeof(dmat3) == 72, "sizeof(dmat3) == 72"); | |||||
/* | /* | ||||
* 4×4-element matrices | * 4×4-element matrices | ||||
*/ | */ | ||||
template <typename T> | template <typename T> | ||||
struct mat_t<T, 4, 4> : public linear_ops::base | |||||
struct mat_t<T, 4, 4> | |||||
: public linear_ops::base<vec_t<T,4>> | |||||
{ | { | ||||
static int const count = 4; | |||||
typedef vec_t<T,4> element; | |||||
typedef mat_t<T,4,4> type; | typedef mat_t<T,4,4> type; | ||||
inline mat_t() {} | inline mat_t() {} | ||||
@@ -388,6 +418,15 @@ private: | |||||
#endif | #endif | ||||
}; | }; | ||||
static_assert(sizeof(i8mat4) == 16, "sizeof(i8mat4) == 16"); | |||||
static_assert(sizeof(i16mat4) == 32, "sizeof(i16mat4) == 32"); | |||||
static_assert(sizeof(imat4) == 64, "sizeof(imat4) == 64"); | |||||
static_assert(sizeof(i64mat4) == 128, "sizeof(i64mat4) == 128"); | |||||
static_assert(sizeof(f16mat4) == 32, "sizeof(f16mat4) == 32"); | |||||
static_assert(sizeof(mat4) == 64, "sizeof(mat4) == 64"); | |||||
static_assert(sizeof(dmat4) == 128, "sizeof(dmat4) == 128"); | |||||
template<typename T> T determinant(mat_t<T,2,2> const &); | template<typename T> T determinant(mat_t<T,2,2> const &); | ||||
template<typename T> T determinant(mat_t<T,3,3> const &); | template<typename T> T determinant(mat_t<T,3,3> const &); | ||||
template<typename T> T determinant(mat_t<T,4,4> const &); | template<typename T> T determinant(mat_t<T,4,4> const &); | ||||
@@ -406,53 +445,6 @@ static inline mat_t<T, ROWS, COLS> transpose(mat_t<T, COLS, ROWS> const &m) | |||||
return ret; | return ret; | ||||
} | } | ||||
/* | |||||
* Addition/subtraction/unary | |||||
*/ | |||||
template<typename T, int COLS, int ROWS> | |||||
static inline mat_t<T, COLS, ROWS> &operator +=(mat_t<T, COLS, ROWS> &a, | |||||
mat_t<T, COLS, ROWS> const &b) | |||||
{ | |||||
for (int i = 0; i < COLS; ++i) | |||||
a[i] += b[i]; | |||||
return a; | |||||
} | |||||
template<typename T, int COLS, int ROWS> | |||||
static inline mat_t<T, COLS, ROWS> operator +(mat_t<T, COLS, ROWS> const &a, | |||||
mat_t<T, COLS, ROWS> const &b) | |||||
{ | |||||
mat_t<T, COLS, ROWS> ret = a; | |||||
return ret += b; | |||||
} | |||||
template<typename T, int COLS, int ROWS> | |||||
static inline mat_t<T, COLS, ROWS> &operator -=(mat_t<T, COLS, ROWS> &a, | |||||
mat_t<T, COLS, ROWS> const &b) | |||||
{ | |||||
for (int i = 0; i < COLS; ++i) | |||||
a[i] -= b[i]; | |||||
return a; | |||||
} | |||||
template<typename T, int COLS, int ROWS> | |||||
static inline mat_t<T, COLS, ROWS> operator -(mat_t<T, COLS, ROWS> const &a, | |||||
mat_t<T, COLS, ROWS> const &b) | |||||
{ | |||||
mat_t<T, COLS, ROWS> ret = a; | |||||
return ret -= b; | |||||
} | |||||
template<typename T, int COLS, int ROWS> | |||||
static inline mat_t<T, COLS, ROWS> operator -(mat_t<T, COLS, ROWS> const &m) | |||||
{ | |||||
mat_t<T, COLS, ROWS> ret; | |||||
for (int i = 0; i < COLS; ++i) | |||||
ret[i] = -m[i]; | |||||
return ret; | |||||
} | |||||
/* | /* | ||||
* Matrix-vector and vector-matrix multiplication | * Matrix-vector and vector-matrix multiplication | ||||
*/ | */ | ||||
@@ -0,0 +1,344 @@ | |||||
// | |||||
// Lol Engine | |||||
// | |||||
// Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net> | |||||
// This program is free software; you can redistribute it and/or | |||||
// modify it under the terms of the Do What The Fuck You Want To | |||||
// Public License, Version 2, as published by Sam Hocevar. See | |||||
// http://www.wtfpl.net/ for more details. | |||||
// | |||||
// | |||||
// Operations for vector classes | |||||
// ----------------------------- | |||||
// | |||||
#if !defined __LOL_MATH_OPS_H__ | |||||
#define __LOL_MATH_OPS_H__ | |||||
#include <ostream> | |||||
#include <type_traits> | |||||
#include <lol/math/half.h> | |||||
#include <lol/math/real.h> | |||||
/* | |||||
* Utility namespaces for traits -- this file uses a combination of | |||||
* ADL black magic and enable_if to ensure that only the expected type | |||||
* conversions are done. | |||||
*/ | |||||
namespace lol | |||||
{ | |||||
/* | |||||
* Operators for swizzled vectors. Since template deduction cannot be | |||||
* done for two arbitrary vec_t<> values, we help the compiler understand | |||||
* the expected type. | |||||
*/ | |||||
namespace swizzle_ops | |||||
{ | |||||
template<typename T, int SWIZZLE = FULL_SWIZZLE> | |||||
struct base {}; | |||||
template<typename T, int N, int SWIZZLE1, int SWIZZLE2> | |||||
static inline typename std::enable_if<SWIZZLE1 != FULL_SWIZZLE || SWIZZLE2 != FULL_SWIZZLE, bool>::type operator ==(vec_t<T,N,SWIZZLE1> const &a, | |||||
vec_t<T,N,SWIZZLE2> const &b) | |||||
{ | |||||
return vec_t<T,N>(a) == vec_t<T,N>(b); | |||||
} | |||||
template<typename T, int N, int SWIZZLE1, int SWIZZLE2> | |||||
static inline typename std::enable_if<SWIZZLE1 != FULL_SWIZZLE || SWIZZLE2 != FULL_SWIZZLE, bool>::type operator !=(vec_t<T,N,SWIZZLE1> const &a, | |||||
vec_t<T,N,SWIZZLE2> const &b) | |||||
{ | |||||
return vec_t<T,N>(a) != vec_t<T,N>(b); | |||||
} | |||||
#define LOL_SWIZZLE_V_VV_OP(op) \ | |||||
template<typename T, int N, int SWIZZLE1, int SWIZZLE2> \ | |||||
inline typename std::enable_if<SWIZZLE1 != FULL_SWIZZLE \ | |||||
|| SWIZZLE2 != FULL_SWIZZLE,vec_t<T,N>>::type \ | |||||
operator op(vec_t<T,N,SWIZZLE1> const &a, \ | |||||
vec_t<T,N,SWIZZLE2> const &b) \ | |||||
{ \ | |||||
return vec_t<T,N>(a) op vec_t<T,N>(b); \ | |||||
} \ | |||||
\ | |||||
template<typename T, int N, int SWIZZLE> \ | |||||
inline typename std::enable_if<SWIZZLE != FULL_SWIZZLE,vec_t<T,N>>::type & \ | |||||
operator op##=(vec_t<T,N> &a, \ | |||||
vec_t<T,N,SWIZZLE> const &b) \ | |||||
{ \ | |||||
return a op##= vec_t<T,N>(b); \ | |||||
} \ | |||||
\ | |||||
template<typename T, int N, int SWIZZLE> \ | |||||
inline typename std::enable_if<SWIZZLE != FULL_SWIZZLE,vec_t<T,N>>::type \ | |||||
operator op(vec_t<T,N,SWIZZLE> a, T const &b) \ | |||||
{ \ | |||||
return vec_t<T,N>(a) op b; \ | |||||
} | |||||
LOL_SWIZZLE_V_VV_OP(+) | |||||
LOL_SWIZZLE_V_VV_OP(-) | |||||
LOL_SWIZZLE_V_VV_OP(*) | |||||
LOL_SWIZZLE_V_VV_OP(/) | |||||
#undef LOL_SWIZZLE_V_VV_OP | |||||
} /* namespace swizzle_ops */ | |||||
/* | |||||
* Linear operations: operators and functions that work on all types | |||||
* (vectors, matrices, quaternions...) such as addition or equality test. | |||||
* | |||||
* Others, e.g. multiplication, cannot be implemented here, since it should | |||||
* be implemented as per-component multiplication for vectors, and matrix | |||||
* product for matrices. | |||||
*/ | |||||
namespace linear_ops | |||||
{ | |||||
template<typename T> | |||||
struct base {}; | |||||
/* | |||||
* Comparisons | |||||
*/ | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, bool>::type | |||||
operator ==(V const &a, V const &b) | |||||
{ | |||||
for (int i = 0; i < V::count; ++i) | |||||
if (!(a[i] == b[i])) | |||||
return false; | |||||
return true; | |||||
} | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, bool>::type | |||||
operator !=(V const &a, V const &b) | |||||
{ | |||||
for (int i = 0; i < V::count; ++i) | |||||
if (a[i] != b[i]) | |||||
return true; | |||||
return false; | |||||
} | |||||
/* | |||||
* Unary plus and minus | |||||
*/ | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, typename V::type>::type | |||||
operator +(V const &v) | |||||
{ | |||||
return v; | |||||
} | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, typename V::type>::type | |||||
operator -(V const &v) | |||||
{ | |||||
typename V::type ret; | |||||
for (int i = 0; i < V::count; ++i) | |||||
ret[i] = -v[i]; | |||||
return ret; | |||||
} | |||||
/* | |||||
* Addition and subtraction | |||||
*/ | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, typename V::type>::type | |||||
operator +(V const &a, V const &b) | |||||
{ | |||||
typename V::type ret; | |||||
for (int i = 0; i < V::count; ++i) | |||||
ret[i] = a[i] + b[i]; | |||||
return ret; | |||||
} | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, typename V::type>::type | |||||
&operator +=(V &a, V const &b) | |||||
{ | |||||
return a = a + b; | |||||
} | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, typename V::type>::type | |||||
operator -(V const &a, V const &b) | |||||
{ | |||||
typename V::type ret; | |||||
for (int i = 0; i < V::count; ++i) | |||||
ret[i] = a[i] - b[i]; | |||||
return ret; | |||||
} | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, typename V::type>::type | |||||
&operator -=(V &a, V const &b) | |||||
{ | |||||
return a = a - b; | |||||
} | |||||
/* | |||||
* Multiplication by scalar (left) | |||||
*/ | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, typename V::type>::type | |||||
operator *(typename V::element const &val, V const &a) | |||||
{ | |||||
typename V::type ret; | |||||
for (int i = 0; i < V::count; ++i) | |||||
ret[i] = val * a[i]; | |||||
return ret; | |||||
} | |||||
/* | |||||
* Multiplication/division by scalar (right) | |||||
*/ | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, typename V::type>::type | |||||
operator *(V const &a, typename V::element const &val) | |||||
{ | |||||
typename V::type ret; | |||||
for (int i = 0; i < V::count; ++i) | |||||
ret[i] = a[i] * val; | |||||
return ret; | |||||
} | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, typename V::type>::type & | |||||
operator *=(V &a, typename V::element const &val) | |||||
{ | |||||
return a = a * val; | |||||
} | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, typename V::type>::type | |||||
operator /(V const &a, typename V::element const &val) | |||||
{ | |||||
typename V::type ret; | |||||
for (int i = 0; i < V::count; ++i) | |||||
ret[i] = a[i] / val; | |||||
return ret; | |||||
} | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, typename V::type>::type & | |||||
operator /=(V &a, typename V::element const &val) | |||||
{ | |||||
return a = a / val; | |||||
} | |||||
} /* namespace linear_ops */ | |||||
/* | |||||
* Operations that work component-wise, such as comparisons or multiplication. | |||||
* This is only for vector types, as the other types (matrices, quaternions, | |||||
* complexes) have different meanings. | |||||
*/ | |||||
namespace componentwise_ops | |||||
{ | |||||
template<typename T> | |||||
struct base {}; | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, typename V::type>::type | |||||
operator *(V const &a, V const &b) | |||||
{ | |||||
typename V::type ret; | |||||
for (int i = 0; i < V::count; ++i) | |||||
ret[i] = a[i] * b[i]; | |||||
return ret; | |||||
} | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, typename V::type>::type | |||||
&operator *=(V &a, V const &b) | |||||
{ | |||||
return a = a * b; | |||||
} | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, typename V::type>::type | |||||
operator /(V const &a, V const &b) | |||||
{ | |||||
typename V::type ret; | |||||
for (int i = 0; i < V::count; ++i) | |||||
ret[i] = a[i] / b[i]; | |||||
return ret; | |||||
} | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, typename V::type>::type | |||||
&operator /=(V &a, V const &b) | |||||
{ | |||||
return a = a / b; | |||||
} | |||||
/* | |||||
* Comparisons | |||||
*/ | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, bool>::type | |||||
operator <(V const &a, V const &b) | |||||
{ | |||||
for (int i = 0; i < V::count; ++i) | |||||
if (!(a[i] < b[i])) | |||||
return false; | |||||
return true; | |||||
} | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, bool>::type | |||||
operator >(V const &a, V const &b) | |||||
{ | |||||
for (int i = 0; i < V::count; ++i) | |||||
if (!(a[i] > b[i])) | |||||
return false; | |||||
return true; | |||||
} | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, bool>::type | |||||
operator <=(V const &a, V const &b) | |||||
{ | |||||
for (int i = 0; i < V::count; ++i) | |||||
if (!(a[i] <= b[i])) | |||||
return false; | |||||
return true; | |||||
} | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, bool>::type | |||||
operator >=(V const &a, V const &b) | |||||
{ | |||||
for (int i = 0; i < V::count; ++i) | |||||
if (!(a[i] >= b[i])) | |||||
return false; | |||||
return true; | |||||
} | |||||
} /* namespace componentwise_ops */ | |||||
} /* namespace lol */ | |||||
#endif // __LOL_MATH_OPS_H__ | |||||
@@ -30,8 +30,10 @@ namespace lol | |||||
*/ | */ | ||||
template<typename T> | template<typename T> | ||||
struct cmplx_t : public linear_ops::base | |||||
struct cmplx_t : public linear_ops::base<T> | |||||
{ | { | ||||
static int const count = 2; | |||||
typedef T element; | |||||
typedef cmplx_t<T> type; | typedef cmplx_t<T> type; | ||||
inline constexpr cmplx_t() {} | inline constexpr cmplx_t() {} | ||||
@@ -43,7 +45,6 @@ struct cmplx_t : public linear_ops::base | |||||
: x(z.x), y(z.y) {} | : x(z.x), y(z.y) {} | ||||
LOL_COMMON_MEMBER_OPS(x) | LOL_COMMON_MEMBER_OPS(x) | ||||
LOL_NONVECTOR_MEMBER_OPS() | |||||
inline cmplx_t<T> operator *(cmplx_t<T> const &val) const | inline cmplx_t<T> operator *(cmplx_t<T> const &val) const | ||||
{ | { | ||||
@@ -66,13 +67,24 @@ struct cmplx_t : public linear_ops::base | |||||
T x, y; | T x, y; | ||||
}; | }; | ||||
static_assert(sizeof(i8cmplx) == 2, "sizeof(i8cmplx) == 2"); | |||||
static_assert(sizeof(i16cmplx) == 4, "sizeof(i16cmplx) == 4"); | |||||
static_assert(sizeof(icmplx) == 8, "sizeof(icmplx) == 8"); | |||||
static_assert(sizeof(i64cmplx) == 16, "sizeof(i64cmplx) == 16"); | |||||
static_assert(sizeof(f16cmplx) == 4, "sizeof(f16cmplx) == 4"); | |||||
static_assert(sizeof(cmplx) == 8, "sizeof(cmplx) == 8"); | |||||
static_assert(sizeof(dcmplx) == 16, "sizeof(dcmplx) == 16"); | |||||
/* | /* | ||||
* 4-element transforms: quaternions | * 4-element transforms: quaternions | ||||
*/ | */ | ||||
template<typename T> | template<typename T> | ||||
struct quat_t : public linear_ops::base | |||||
struct quat_t : public linear_ops::base<T> | |||||
{ | { | ||||
static int const count = 4; | |||||
typedef T element; | |||||
typedef quat_t<T> type; | typedef quat_t<T> type; | ||||
/* Default constructor and copy constructor */ | /* Default constructor and copy constructor */ | ||||
@@ -95,7 +107,6 @@ struct quat_t : public linear_ops::base | |||||
explicit quat_t(mat_t<T,4,4> const &m); | explicit quat_t(mat_t<T,4,4> const &m); | ||||
LOL_COMMON_MEMBER_OPS(w) | LOL_COMMON_MEMBER_OPS(w) | ||||
LOL_NONVECTOR_MEMBER_OPS() | |||||
inline quat_t operator *(quat_t const &val) const | inline quat_t operator *(quat_t const &val) const | ||||
{ | { | ||||
@@ -210,6 +221,15 @@ struct quat_t : public linear_ops::base | |||||
T w, x, y, z; | T w, x, y, z; | ||||
}; | }; | ||||
static_assert(sizeof(i8quat) == 4, "sizeof(i8quat) == 4"); | |||||
static_assert(sizeof(i16quat) == 8, "sizeof(i16quat) == 8"); | |||||
static_assert(sizeof(iquat) == 16, "sizeof(iquat) == 16"); | |||||
static_assert(sizeof(i64quat) == 32, "sizeof(i64quat) == 32"); | |||||
static_assert(sizeof(f16quat) == 8, "sizeof(f16quat) == 8"); | |||||
static_assert(sizeof(quat) == 16, "sizeof(quat) == 16"); | |||||
static_assert(sizeof(dquat) == 32, "sizeof(dquat) == 32"); | |||||
/* | /* | ||||
* Common operations on transforms | * Common operations on transforms | ||||
*/ | */ | ||||
@@ -17,10 +17,10 @@ | |||||
#define __LOL_MATH_VECTOR_H__ | #define __LOL_MATH_VECTOR_H__ | ||||
#include <ostream> | #include <ostream> | ||||
#include <type_traits> | |||||
#include <lol/math/half.h> | #include <lol/math/half.h> | ||||
#include <lol/math/real.h> | #include <lol/math/real.h> | ||||
#include <lol/math/ops.h> | |||||
namespace lol | namespace lol | ||||
{ | { | ||||
@@ -35,169 +35,6 @@ namespace lol | |||||
# define _____ /* */ | # define _____ /* */ | ||||
#endif | #endif | ||||
/* | |||||
* Utility namespaces for traits | |||||
*/ | |||||
namespace swizzle_ops | |||||
{ | |||||
} | |||||
namespace linear_ops | |||||
{ | |||||
struct base {}; | |||||
/* | |||||
* Unary plus and minus | |||||
*/ | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base, V>::value, V>::type | |||||
operator +(V const &v) | |||||
{ | |||||
return v; | |||||
} | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base, V>::value, V>::type | |||||
operator -(V const &v) | |||||
{ | |||||
V ret; | |||||
for (size_t i = 0; i < sizeof(ret) / sizeof(ret[0]); ++i) | |||||
ret[i] = -v[i]; | |||||
return ret; | |||||
} | |||||
/* | |||||
* Addition and subtraction | |||||
*/ | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base, V>::value, V>::type | |||||
operator +(V const &a, V const &b) | |||||
{ | |||||
V ret; | |||||
for (size_t i = 0; i < sizeof(ret) / sizeof(ret[0]); ++i) | |||||
ret[i] = a[i] + b[i]; | |||||
return ret; | |||||
} | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base, V>::value, V>::type | |||||
&operator +=(V &a, V const &b) | |||||
{ | |||||
return a = a + b; | |||||
} | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base, V>::value, V>::type | |||||
operator -(V const &a, V const &b) | |||||
{ | |||||
V ret; | |||||
for (size_t i = 0; i < sizeof(ret) / sizeof(ret[0]); ++i) | |||||
ret[i] = a[i] - b[i]; | |||||
return ret; | |||||
} | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base, V>::value, V>::type | |||||
&operator -=(V &a, V const &b) | |||||
{ | |||||
return a = a - b; | |||||
} | |||||
} /* namespace linear_ops */ | |||||
namespace componentwise_ops | |||||
{ | |||||
struct base {}; | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base, V>::value, V>::type | |||||
operator *(V const &a, V const &b) | |||||
{ | |||||
V ret; | |||||
for (size_t i = 0; i < sizeof(ret) / sizeof(ret[0]); ++i) | |||||
ret[i] = a[i] * b[i]; | |||||
return ret; | |||||
} | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base, V>::value, V>::type | |||||
&operator *=(V &a, V const &b) | |||||
{ | |||||
return a = a * b; | |||||
} | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base, V>::value, V>::type | |||||
operator /(V const &a, V const &b) | |||||
{ | |||||
V ret; | |||||
for (size_t i = 0; i < sizeof(ret) / sizeof(ret[0]); ++i) | |||||
ret[i] = a[i] / b[i]; | |||||
return ret; | |||||
} | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base, V>::value, V>::type | |||||
&operator /=(V &a, V const &b) | |||||
{ | |||||
return a = a / b; | |||||
} | |||||
/* | |||||
* Comparisons | |||||
*/ | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base, V>::value, bool>::type | |||||
operator <(V const &a, V const &b) | |||||
{ | |||||
for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i) | |||||
if (!(a[i] < b[i])) | |||||
return false; | |||||
return true; | |||||
} | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base, V>::value, bool>::type | |||||
operator >(V const &a, V const &b) | |||||
{ | |||||
for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i) | |||||
if (!(a[i] > b[i])) | |||||
return false; | |||||
return true; | |||||
} | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base, V>::value, bool>::type | |||||
operator <=(V const &a, V const &b) | |||||
{ | |||||
for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i) | |||||
if (!(a[i] <= b[i])) | |||||
return false; | |||||
return true; | |||||
} | |||||
template<typename V> | |||||
static inline typename std::enable_if<std::is_base_of<base, V>::value, bool>::type | |||||
operator >=(V const &a, V const &b) | |||||
{ | |||||
for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i) | |||||
if (!(a[i] >= b[i])) | |||||
return false; | |||||
return true; | |||||
} | |||||
} /* namespace componentwise_ops */ | |||||
/* | /* | ||||
* Magic vector swizzling (part 1/2) | * Magic vector swizzling (part 1/2) | ||||
* These vectors are empty, but thanks to static_cast we can take their | * These vectors are empty, but thanks to static_cast we can take their | ||||
@@ -214,7 +51,13 @@ operator >=(V const &a, V const &b) | |||||
template<typename T, int N, int SWIZZLE> | template<typename T, int N, int SWIZZLE> | ||||
struct vec_t | struct vec_t | ||||
/* MUST be a different base than e.g. vec_t<T,2> otherwise the unions | |||||
* in vec_t<T,2> with the same base will cause empty base optimisation | |||||
* failures. */ | |||||
: public swizzle_ops::base<T, SWIZZLE> | |||||
{ | { | ||||
static int const count = N; | |||||
typedef T element; | |||||
typedef vec_t<T,N> type; | typedef vec_t<T,N> type; | ||||
inline vec_t<T, N, SWIZZLE>& operator =(vec_t<T, N> that); | inline vec_t<T, N, SWIZZLE>& operator =(vec_t<T, N> that); | ||||
@@ -244,9 +87,11 @@ struct vec_t | |||||
* swizzling. There's an override for N=2, N=3, N=4 that has swizzling. */ | * swizzling. There's an override for N=2, N=3, N=4 that has swizzling. */ | ||||
template<typename T, int N> | template<typename T, int N> | ||||
struct vec_t<T, N, FULL_SWIZZLE> | struct vec_t<T, N, FULL_SWIZZLE> | ||||
: public linear_ops::base, | |||||
public componentwise_ops::base | |||||
: public linear_ops::base<T>, | |||||
public componentwise_ops::base<T> | |||||
{ | { | ||||
static int const count = N; | |||||
typedef T element; | |||||
typedef vec_t<T,N> type; | typedef vec_t<T,N> type; | ||||
inline T& operator[](size_t n) { return m_data[n]; } | inline T& operator[](size_t n) { return m_data[n]; } | ||||
@@ -260,30 +105,6 @@ private: | |||||
* Helper macros for vector type member functions | * Helper macros for vector type member functions | ||||
*/ | */ | ||||
#define LOL_V_VS_OP(op) \ | |||||
friend inline type operator op(type const &a, T const &val) \ | |||||
{ \ | |||||
type ret; \ | |||||
for (size_t i = 0; i < sizeof(type) / sizeof(T); ++i) \ | |||||
ret[i] = a[i] op val; \ | |||||
return ret; \ | |||||
} | |||||
#define LOL_V_VS_ASSIGN_OP(op) \ | |||||
friend inline type operator op##=(type &a, T const &val) \ | |||||
{ \ | |||||
return a = a op val; \ | |||||
} | |||||
#define LOL_B_VV_OP(op, op2, ret) \ | |||||
friend inline bool operator op(type const &a, type const &b) \ | |||||
{ \ | |||||
for (size_t i = 0; i < sizeof(type) / sizeof(T); ++i) \ | |||||
if (!(a[i] op2 b[i])) \ | |||||
return !ret; \ | |||||
return ret; \ | |||||
} | |||||
#define LOL_COMMON_MEMBER_OPS(first) \ | #define LOL_COMMON_MEMBER_OPS(first) \ | ||||
inline T& operator[](size_t n) { return (&this->first)[n]; } \ | inline T& operator[](size_t n) { return (&this->first)[n]; } \ | ||||
inline T const& operator[](size_t n) const { return (&this->first)[n]; } \ | inline T const& operator[](size_t n) const { return (&this->first)[n]; } \ | ||||
@@ -291,37 +112,13 @@ private: | |||||
/* Visual Studio insists on having an assignment operator. */ \ | /* Visual Studio insists on having an assignment operator. */ \ | ||||
inline type & operator =(type const &that) \ | inline type & operator =(type const &that) \ | ||||
{ \ | { \ | ||||
for (size_t i = 0; i < sizeof(type) / sizeof(T); ++i) \ | |||||
for (int i = 0; i < type::count; ++i) \ | |||||
(*this)[i] = that[i]; \ | (*this)[i] = that[i]; \ | ||||
return *this; \ | return *this; \ | ||||
} \ | } \ | ||||
\ | \ | ||||
void printf() const; \ | void printf() const; \ | ||||
String tostring() const; \ | |||||
\ | |||||
/* vec_t *(vec_t, scalar) | |||||
* vec_t /(vec_t, scalar) | |||||
* vec_t *=(vec_t, scalar) | |||||
* vec_t /=(vec_t, scalar) */ \ | |||||
LOL_V_VS_OP(*) \ | |||||
LOL_V_VS_OP(/) \ | |||||
LOL_V_VS_ASSIGN_OP(*) \ | |||||
LOL_V_VS_ASSIGN_OP(/) \ | |||||
\ | |||||
/* bool ==(vec_t, vec_t) | |||||
* bool !=(vec_t, vec_t) */ \ | |||||
LOL_B_VV_OP(==, ==, true) \ | |||||
LOL_B_VV_OP(!=, ==, false) | |||||
#define LOL_NONVECTOR_MEMBER_OPS() \ | |||||
/* vec_t *(scalar, vec_t) (no division, it works differently) */ \ | |||||
friend inline type operator *(T const &val, type const &a) \ | |||||
{ \ | |||||
type ret; \ | |||||
for (size_t i = 0; i < sizeof(type) / sizeof(T); ++i) \ | |||||
ret[i] = val * a[i]; \ | |||||
return ret; \ | |||||
} | |||||
String tostring() const; | |||||
/* | /* | ||||
* 2-element vectors | * 2-element vectors | ||||
@@ -329,9 +126,12 @@ private: | |||||
template <typename T> | template <typename T> | ||||
struct vec_t<T,2> | struct vec_t<T,2> | ||||
: public linear_ops::base, | |||||
public componentwise_ops::base | |||||
: public swizzle_ops::base<T>, | |||||
public linear_ops::base<T>, | |||||
public componentwise_ops::base<T> | |||||
{ | { | ||||
static int const count = 2; | |||||
typedef T element; | |||||
typedef vec_t<T,2> type; | typedef vec_t<T,2> type; | ||||
/* Default constructor, copy constructor, and destructor */ | /* Default constructor, copy constructor, and destructor */ | ||||
@@ -405,15 +205,27 @@ struct vec_t<T,2> | |||||
}; | }; | ||||
}; | }; | ||||
static_assert(sizeof(i8vec2) == 2, "sizeof(i8vec2) == 2"); | |||||
static_assert(sizeof(i16vec2) == 4, "sizeof(i16vec2) == 4"); | |||||
static_assert(sizeof(ivec2) == 8, "sizeof(ivec2) == 8"); | |||||
static_assert(sizeof(i64vec2) == 16, "sizeof(i64vec2) == 16"); | |||||
static_assert(sizeof(f16vec2) == 4, "sizeof(f16vec2) == 4"); | |||||
static_assert(sizeof(vec2) == 8, "sizeof(vec2) == 8"); | |||||
static_assert(sizeof(dvec2) == 16, "sizeof(dvec2) == 16"); | |||||
/* | /* | ||||
* 3-element vectors | * 3-element vectors | ||||
*/ | */ | ||||
template <typename T> | template <typename T> | ||||
struct vec_t<T,3> | struct vec_t<T,3> | ||||
: public linear_ops::base, | |||||
public componentwise_ops::base | |||||
: public swizzle_ops::base<T>, | |||||
public linear_ops::base<T>, | |||||
public componentwise_ops::base<T> | |||||
{ | { | ||||
static int const count = 3; | |||||
typedef T element; | |||||
typedef vec_t<T,3> type; | typedef vec_t<T,3> type; | ||||
/* Default constructor, copy constructor, and destructor */ | /* Default constructor, copy constructor, and destructor */ | ||||
@@ -617,15 +429,27 @@ struct vec_t<T,3> | |||||
}; | }; | ||||
}; | }; | ||||
static_assert(sizeof(i8vec3) == 3, "sizeof(i8vec3) == 3"); | |||||
static_assert(sizeof(i16vec3) == 6, "sizeof(i16vec3) == 6"); | |||||
static_assert(sizeof(ivec3) == 12, "sizeof(ivec3) == 12"); | |||||
static_assert(sizeof(i64vec3) == 24, "sizeof(i64vec3) == 24"); | |||||
static_assert(sizeof(f16vec3) == 6, "sizeof(f16vec3) == 6"); | |||||
static_assert(sizeof(vec3) == 12, "sizeof(vec3) == 12"); | |||||
static_assert(sizeof(dvec3) == 24, "sizeof(dvec3) == 24"); | |||||
/* | /* | ||||
* 4-element vectors | * 4-element vectors | ||||
*/ | */ | ||||
template <typename T> | template <typename T> | ||||
struct vec_t<T,4> | struct vec_t<T,4> | ||||
: public linear_ops::base, | |||||
public componentwise_ops::base | |||||
: public swizzle_ops::base<T>, | |||||
public linear_ops::base<T>, | |||||
public componentwise_ops::base<T> | |||||
{ | { | ||||
static int const count = 4; | |||||
typedef T element; | |||||
typedef vec_t<T,4> type; | typedef vec_t<T,4> type; | ||||
/* Default constructor, copy constructor, and destructor */ | /* Default constructor, copy constructor, and destructor */ | ||||
@@ -1022,68 +846,24 @@ struct vec_t<T,4> | |||||
}; | }; | ||||
}; | }; | ||||
/* | |||||
* Operators for swizzled vectors. Since template deduction cannot be | |||||
* done for two arbitrary vec_t<> values, we help the compiler understand | |||||
* the expected type. | |||||
*/ | |||||
static_assert(sizeof(i8vec4) == 4, "sizeof(i8vec4) == 4"); | |||||
static_assert(sizeof(i16vec4) == 8, "sizeof(i16vec4) == 8"); | |||||
static_assert(sizeof(ivec4) == 16, "sizeof(ivec4) == 16"); | |||||
static_assert(sizeof(i64vec4) == 32, "sizeof(i64vec4) == 32"); | |||||
template<typename T, int N, int SWIZZLE1, int SWIZZLE2> | |||||
static inline bool operator ==(vec_t<T,N,SWIZZLE1> const &a, | |||||
vec_t<T,N,SWIZZLE2> const &b) | |||||
{ | |||||
for (size_t i = 0; i < N; ++i) | |||||
if (!(a[i] == b[i])) | |||||
return false; | |||||
return true; | |||||
} | |||||
template<typename T, int N, int SWIZZLE1, int SWIZZLE2> | |||||
static inline bool operator !=(vec_t<T,N,SWIZZLE1> const &a, | |||||
vec_t<T,N,SWIZZLE2> const &b) | |||||
{ | |||||
for (size_t i = 0; i < N; ++i) | |||||
if (a[i] != b[i]) | |||||
return true; | |||||
return false; | |||||
} | |||||
static_assert(sizeof(f16vec4) == 8, "sizeof(f16vec4) == 8"); | |||||
static_assert(sizeof(vec4) == 16, "sizeof(vec4) == 16"); | |||||
static_assert(sizeof(dvec4) == 32, "sizeof(dvec4) == 32"); | |||||
#define LOL_SWIZZLE_V_VV_OP(op) \ | |||||
template<typename T, int N, int SWIZZLE1, int SWIZZLE2> \ | |||||
inline typename std::enable_if<SWIZZLE1 != FULL_SWIZZLE \ | |||||
|| SWIZZLE2 != FULL_SWIZZLE,vec_t<T,N>>::type \ | |||||
operator op(vec_t<T,N,SWIZZLE1> const &a, \ | |||||
vec_t<T,N,SWIZZLE2> const &b) \ | |||||
{ \ | |||||
return vec_t<T,N>(a) op vec_t<T,N>(b); \ | |||||
} \ | |||||
\ | |||||
template<typename T, int N, int SWIZZLE> \ | |||||
inline typename std::enable_if<SWIZZLE != FULL_SWIZZLE,vec_t<T,N>>::type & \ | |||||
operator op##=(vec_t<T,N> &a, \ | |||||
vec_t<T,N,SWIZZLE> const &b) \ | |||||
{ \ | |||||
return a op##= vec_t<T,N>(b); \ | |||||
} \ | |||||
\ | |||||
template<typename T, int N, int SWIZZLE> \ | |||||
inline vec_t<T,N> operator op(vec_t<T,N,SWIZZLE> a, T const &b) \ | |||||
{ \ | |||||
return vec_t<T,N>(a) op b; \ | |||||
} | |||||
LOL_SWIZZLE_V_VV_OP(+) | |||||
LOL_SWIZZLE_V_VV_OP(-) | |||||
LOL_SWIZZLE_V_VV_OP(*) | |||||
LOL_SWIZZLE_V_VV_OP(/) | |||||
#undef LOL_SWIZZLE_V_VV_OP | |||||
/* | |||||
* vec_t *(scalar, vec_t) | |||||
*/ | |||||
template<typename T, int N, int SWIZZLE> | template<typename T, int N, int SWIZZLE> | ||||
static inline vec_t<T,N> operator *(T const &val, vec_t<T,N,SWIZZLE> const &a) | static inline vec_t<T,N> operator *(T const &val, vec_t<T,N,SWIZZLE> const &a) | ||||
{ | { | ||||
vec_t<T,N> ret; | vec_t<T,N> ret; | ||||
for (size_t i = 0; i < N; ++i) | |||||
for (int i = 0; i < N; ++i) | |||||
ret[i] = val * a[i]; | ret[i] = val * a[i]; | ||||
return ret; | return ret; | ||||
} | } | ||||
@@ -1100,7 +880,7 @@ static inline vec_t<T,N> operator *(T const &val, vec_t<T,N,SWIZZLE> const &a) | |||||
{ \ | { \ | ||||
using lol::fun; \ | using lol::fun; \ | ||||
vec_t<T,N> ret; \ | vec_t<T,N> ret; \ | ||||
for (size_t i = 0; i < N; ++i) \ | |||||
for (int i = 0; i < N; ++i) \ | |||||
ret[i] = fun(a[i], b[i]); \ | ret[i] = fun(a[i], b[i]); \ | ||||
return ret; \ | return ret; \ | ||||
} \ | } \ | ||||
@@ -1110,7 +890,7 @@ static inline vec_t<T,N> operator *(T const &val, vec_t<T,N,SWIZZLE> const &a) | |||||
{ \ | { \ | ||||
using lol::fun; \ | using lol::fun; \ | ||||
vec_t<T,N> ret; \ | vec_t<T,N> ret; \ | ||||
for (size_t i = 0; i < N; ++i) \ | |||||
for (int i = 0; i < N; ++i) \ | |||||
ret[i] = fun(a[i], b); \ | ret[i] = fun(a[i], b); \ | ||||
return ret; \ | return ret; \ | ||||
} \ | } \ | ||||
@@ -1120,7 +900,7 @@ static inline vec_t<T,N> operator *(T const &val, vec_t<T,N,SWIZZLE> const &a) | |||||
{ \ | { \ | ||||
using lol::fun; \ | using lol::fun; \ | ||||
vec_t<T,N> ret; \ | vec_t<T,N> ret; \ | ||||
for (size_t i = 0; i < N; ++i) \ | |||||
for (int i = 0; i < N; ++i) \ | |||||
ret[i] = fun(a, b[i]); \ | ret[i] = fun(a, b[i]); \ | ||||
return ret; \ | return ret; \ | ||||
} | } | ||||
@@ -1200,7 +980,7 @@ static inline T dot(vec_t<T,N,SWIZZLE1> const &a, | |||||
vec_t<T,N,SWIZZLE2> const &b) | vec_t<T,N,SWIZZLE2> const &b) | ||||
{ | { | ||||
T ret(0); | T ret(0); | ||||
for (size_t i = 0; i < N; ++i) | |||||
for (int i = 0; i < N; ++i) | |||||
ret += a[i] * b[i]; | ret += a[i] * b[i]; | ||||
return ret; | return ret; | ||||
} | } | ||||
@@ -1224,7 +1004,7 @@ static inline vec_t<T,N> lerp(vec_t<T,N,SWIZZLE1> const &a, | |||||
T const &s) | T const &s) | ||||
{ | { | ||||
vec_t<T,N> ret; | vec_t<T,N> ret; | ||||
for (size_t i = 0; i < N; ++i) | |||||
for (int i = 0; i < N; ++i) | |||||
ret[i] = a[i] + s * (b[i] - a[i]); | ret[i] = a[i] + s * (b[i] - a[i]); | ||||
return ret; | return ret; | ||||
} | } | ||||
@@ -1240,7 +1020,7 @@ template<typename T, int N, int SWIZZLE> | |||||
static inline vec_t<T,N> fract(vec_t<T,N,SWIZZLE> const &a) | static inline vec_t<T,N> fract(vec_t<T,N,SWIZZLE> const &a) | ||||
{ | { | ||||
vec_t<T,N> ret; | vec_t<T,N> ret; | ||||
for (size_t i = 0; i < N; ++i) | |||||
for (int i = 0; i < N; ++i) | |||||
ret[i] = fract(a[i]); | ret[i] = fract(a[i]); | ||||
return ret; | return ret; | ||||
} | } | ||||
@@ -1256,7 +1036,7 @@ template<typename T, int N, int SWIZZLE> | |||||
static inline vec_t<T,N> abs(vec_t<T,N,SWIZZLE> const &a) | static inline vec_t<T,N> abs(vec_t<T,N,SWIZZLE> const &a) | ||||
{ | { | ||||
vec_t<T,N> ret; | vec_t<T,N> ret; | ||||
for (size_t i = 0; i < N; ++i) | |||||
for (int i = 0; i < N; ++i) | |||||
ret[i] = lol::abs(a[i]); | ret[i] = lol::abs(a[i]); | ||||
return ret; | return ret; | ||||
} | } | ||||
@@ -1265,7 +1045,7 @@ template<typename T, int N, int SWIZZLE> | |||||
static inline vec_t<T,N> degrees(vec_t<T,N,SWIZZLE> const &a) | static inline vec_t<T,N> degrees(vec_t<T,N,SWIZZLE> const &a) | ||||
{ | { | ||||
vec_t<T,N> ret; | vec_t<T,N> ret; | ||||
for (size_t i = 0; i < N; ++i) | |||||
for (int i = 0; i < N; ++i) | |||||
ret[i] = lol::degrees(a[i]); | ret[i] = lol::degrees(a[i]); | ||||
return ret; | return ret; | ||||
} | } | ||||
@@ -1274,7 +1054,7 @@ template<typename T, int N, int SWIZZLE> | |||||
static inline vec_t<T,N> radians(vec_t<T,N,SWIZZLE> const &a) | static inline vec_t<T,N> radians(vec_t<T,N,SWIZZLE> const &a) | ||||
{ | { | ||||
vec_t<T,N> ret; | vec_t<T,N> ret; | ||||
for (size_t i = 0; i < N; ++i) | |||||
for (int i = 0; i < N; ++i) | |||||
ret[i] = lol::radians(a[i]); | ret[i] = lol::radians(a[i]); | ||||
return ret; | return ret; | ||||
} | } | ||||
@@ -327,6 +327,7 @@ | |||||
<ClInclude Include="lol\math\half.h" /> | <ClInclude Include="lol\math\half.h" /> | ||||
<ClInclude Include="lol\math\interp.h" /> | <ClInclude Include="lol\math\interp.h" /> | ||||
<ClInclude Include="lol\math\matrix.h" /> | <ClInclude Include="lol\math\matrix.h" /> | ||||
<ClInclude Include="lol\math\ops.h" /> | |||||
<ClInclude Include="lol\math\rand.h" /> | <ClInclude Include="lol\math\rand.h" /> | ||||
<ClInclude Include="lol\math\real.h" /> | <ClInclude Include="lol\math\real.h" /> | ||||
<ClInclude Include="lol\math\remez.h" /> | <ClInclude Include="lol\math\remez.h" /> | ||||
@@ -441,6 +441,9 @@ | |||||
<ClInclude Include="lol\math\matrix.h"> | <ClInclude Include="lol\math\matrix.h"> | ||||
<Filter>lol\math</Filter> | <Filter>lol\math</Filter> | ||||
</ClInclude> | </ClInclude> | ||||
<ClInclude Include="lol\math\ops.h"> | |||||
<Filter>lol\math</Filter> | |||||
</ClInclude> | |||||
<ClInclude Include="lol\math\rand.h"> | <ClInclude Include="lol\math\rand.h"> | ||||
<Filter>lol\math</Filter> | <Filter>lol\math</Filter> | ||||
</ClInclude> | </ClInclude> | ||||