@@ -44,6 +44,7 @@ liblolcore_headers = \ | |||
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/array3d.h lol/math/constants.h lol/math/matrix.h \ | |||
lol/math/transform.h \ | |||
\ | |||
lol/algorithm/all.h \ | |||
lol/algorithm/sort.h lol/algorithm/portal.h lol/algorithm/aabb_tree.h \ | |||
@@ -11,6 +11,8 @@ | |||
#if !defined __LOL_BASE_TYPES_H__ | |||
#define __LOL_BASE_TYPES_H__ | |||
#include <stdint.h> | |||
namespace lol | |||
{ | |||
@@ -28,9 +30,87 @@ typedef Real<16> real; | |||
/* The “half” type used for 16-bit floating point numbers. */ | |||
class half; | |||
/* Forward declaration of vec and matrix */ | |||
template<int N, typename T, int MASK> struct vec; | |||
/* | |||
* Forward declaration of vec and matrix | |||
*/ | |||
template<int N, typename T, int MASK = -1> struct vec; | |||
template<int COLS, int ROWS, typename T> struct matrix; | |||
template<typename T> struct Cmplx; | |||
template<typename T> struct Quat; | |||
/* | |||
* Generic GLSL-like type names | |||
*/ | |||
#define LOL_VECTOR_TYPEDEFS(tleft, tright, suffix) \ | |||
typedef tleft half tright f16##suffix; \ | |||
typedef tleft float tright suffix; \ | |||
typedef tleft double tright d##suffix; \ | |||
typedef tleft ldouble tright f128##suffix; \ | |||
typedef tleft int8_t tright i8##suffix; \ | |||
typedef tleft uint8_t tright u8##suffix; \ | |||
typedef tleft int16_t tright i16##suffix; \ | |||
typedef tleft uint16_t tright u16##suffix; \ | |||
typedef tleft int32_t tright i##suffix; \ | |||
typedef tleft uint32_t tright u##suffix; \ | |||
typedef tleft int64_t tright i64##suffix; \ | |||
typedef tleft uint64_t tright u64##suffix; \ | |||
typedef tleft real tright r##suffix; | |||
/* Idiotic hack to put "," inside a macro argument */ | |||
#define COMMA , | |||
LOL_VECTOR_TYPEDEFS(vec<2 COMMA, >, vec2) | |||
LOL_VECTOR_TYPEDEFS(vec<3 COMMA, >, vec3) | |||
LOL_VECTOR_TYPEDEFS(vec<4 COMMA, >, vec4) | |||
LOL_VECTOR_TYPEDEFS(matrix<2 COMMA 2 COMMA, >, mat2) | |||
LOL_VECTOR_TYPEDEFS(matrix<3 COMMA 3 COMMA, >, mat3) | |||
LOL_VECTOR_TYPEDEFS(matrix<4 COMMA 4 COMMA, >, mat4) | |||
LOL_VECTOR_TYPEDEFS(matrix<2 COMMA 3 COMMA, >, mat2x3) | |||
LOL_VECTOR_TYPEDEFS(matrix<2 COMMA 4 COMMA, >, mat2x4) | |||
LOL_VECTOR_TYPEDEFS(matrix<3 COMMA 2 COMMA, >, mat3x2) | |||
LOL_VECTOR_TYPEDEFS(matrix<3 COMMA 4 COMMA, >, mat3x4) | |||
LOL_VECTOR_TYPEDEFS(matrix<4 COMMA 2 COMMA, >, mat4x2) | |||
LOL_VECTOR_TYPEDEFS(matrix<4 COMMA 3 COMMA, >, mat4x3) | |||
LOL_VECTOR_TYPEDEFS(Cmplx<, >, cmplx) | |||
LOL_VECTOR_TYPEDEFS(Quat<, >, quat) | |||
#undef COMMA | |||
#undef LOL_VECTOR_TYPEDEFS | |||
/* | |||
* HLSL/Cg-compliant type names | |||
*/ | |||
typedef vec2 float2; | |||
typedef vec3 float3; | |||
typedef vec4 float4; | |||
typedef mat2 float2x2; | |||
typedef mat3 float3x3; | |||
typedef mat4 float4x4; | |||
typedef mat2x3 float2x3; | |||
typedef mat2x4 float2x4; | |||
typedef mat3x2 float3x2; | |||
typedef mat3x4 float3x4; | |||
typedef mat4x2 float4x2; | |||
typedef mat4x3 float4x3; | |||
typedef ivec2 int2; | |||
typedef ivec3 int3; | |||
typedef ivec4 int4; | |||
typedef imat2 int2x2; | |||
typedef imat3 int3x3; | |||
typedef imat4 int4x4; | |||
typedef imat2x3 int2x3; | |||
typedef imat2x4 int2x4; | |||
typedef imat3x2 int3x2; | |||
typedef imat3x4 int3x4; | |||
typedef imat4x2 int4x2; | |||
typedef imat4x3 int4x3; | |||
} /* namespace lol */ | |||
@@ -17,6 +17,7 @@ | |||
#include <lol/math/real.h> | |||
#include <lol/math/vector.h> | |||
#include <lol/math/matrix.h> | |||
#include <lol/math/transform.h> | |||
#include <lol/math/array2d.h> | |||
#include <lol/math/array3d.h> | |||
#include <lol/math/geometry.h> | |||
@@ -16,10 +16,10 @@ | |||
#if !defined __LOL_MATH_MATRIX_H__ | |||
#define __LOL_MATH_MATRIX_H__ | |||
#include <stdint.h> | |||
#include <ostream> | |||
#include <lol/math/vector.h> | |||
#include <lol/math/transform.h> | |||
namespace lol | |||
{ | |||
@@ -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. | |||
// | |||
// | |||
// The complex and quaternion classes | |||
// ---------------------------------- | |||
// | |||
#if !defined __LOL_MATH_TRANSFORM_H__ | |||
#define __LOL_MATH_TRANSFORM_H__ | |||
#include <ostream> | |||
#include <lol/math/half.h> | |||
#include <lol/math/real.h> | |||
namespace lol | |||
{ | |||
#if !LOL_FEATURE_CXX11_CONSTEXPR | |||
# define constexpr /* */ | |||
#endif | |||
/* | |||
* 2-element complexes | |||
*/ | |||
template <typename T> struct Cmplx | |||
{ | |||
typedef Cmplx<T> type; | |||
inline constexpr Cmplx() {} | |||
inline constexpr Cmplx(T X) : x(X), y(T(0)) {} | |||
inline constexpr Cmplx(T X, T Y) : x(X), y(Y) {} | |||
template<typename U> | |||
explicit inline constexpr Cmplx(Cmplx<U> const &z) | |||
: x(z.x), y(z.y) {} | |||
LOL_COMMON_MEMBER_OPS(x) | |||
LOL_NONVECTOR_MEMBER_OPS() | |||
inline Cmplx<T> operator *(Cmplx<T> const &val) const | |||
{ | |||
return Cmplx<T>(x * val.x - y * val.y, x * val.y + y * val.x); | |||
} | |||
inline Cmplx<T> operator *=(Cmplx<T> const &val) | |||
{ | |||
return *this = (*this) * val; | |||
} | |||
inline Cmplx<T> operator ~() const | |||
{ | |||
return Cmplx<T>(x, -y); | |||
} | |||
template<typename U> | |||
friend std::ostream &operator<<(std::ostream &stream, Cmplx<U> const &v); | |||
T x, y; | |||
}; | |||
template<typename T> | |||
static inline T dot(Cmplx<T> const &z1, Cmplx<T> const &z2) | |||
{ | |||
T ret(0); | |||
for (size_t i = 0; i < sizeof(Cmplx<T>) / sizeof(T); ++i) | |||
ret += z1[i] * z2[i]; | |||
return ret; | |||
} | |||
template<typename T> | |||
static inline T sqlength(Cmplx<T> const &z) | |||
{ | |||
return dot(z, z); | |||
} | |||
template<typename T> | |||
static inline T length(Cmplx<T> const &z) | |||
{ | |||
/* FIXME: this is not very nice */ | |||
return (T)sqrt((double)sqlength(z)); | |||
} | |||
template<typename T> | |||
static inline T norm(Cmplx<T> const &z) | |||
{ | |||
return length(z); | |||
} | |||
template<typename T> | |||
static inline Cmplx<T> re(Cmplx<T> const &z) | |||
{ | |||
return ~z / sqlength(z); | |||
} | |||
template<typename T> | |||
static inline Cmplx<T> normalize(Cmplx<T> const &z) | |||
{ | |||
T norm = (T)length(z); | |||
return norm ? z / norm : Cmplx<T>(T(0)); | |||
} | |||
template<typename T> | |||
static inline Cmplx<T> operator /(T a, Cmplx<T> const &b) | |||
{ | |||
return a * re(b); | |||
} | |||
template<typename T> | |||
static inline Cmplx<T> operator /(Cmplx<T> a, Cmplx<T> const &b) | |||
{ | |||
return a * re(b); | |||
} | |||
template<typename T> | |||
static inline bool operator ==(Cmplx<T> const &a, T b) | |||
{ | |||
return (a.x == b) && !a.y; | |||
} | |||
template<typename T> | |||
static inline bool operator !=(Cmplx<T> const &a, T b) | |||
{ | |||
return (a.x != b) || a.y; | |||
} | |||
template<typename T> | |||
static inline bool operator ==(T a, Cmplx<T> const &b) { return b == a; } | |||
template<typename T> | |||
static inline bool operator !=(T a, Cmplx<T> const &b) { return b != a; } | |||
/* | |||
* 4-element quaternions | |||
*/ | |||
template <typename T> struct Quat | |||
{ | |||
typedef Quat<T> type; | |||
inline constexpr Quat() {} | |||
inline constexpr Quat(T W) : w(W), x(0), y(0), z(0) {} | |||
inline constexpr Quat(T W, T X, T Y, T Z) : w(W), x(X), y(Y), z(Z) {} | |||
template<typename U> | |||
explicit inline constexpr Quat(Quat<U> const &q) | |||
: w(q.w), x(q.x), y(q.y), z(q.z) {} | |||
Quat(matrix<3,3,T> const &m); | |||
Quat(matrix<4,4,T> const &m); | |||
LOL_COMMON_MEMBER_OPS(w) | |||
LOL_NONVECTOR_MEMBER_OPS() | |||
/* Create a unit quaternion representing a rotation around an axis. */ | |||
static Quat<T> rotate(T degrees, T x, T y, T z); | |||
static Quat<T> rotate(T degrees, vec<3,T> const &v); | |||
/* Create a unit quaternion representing a rotation between two vectors. | |||
* Input vectors need not be normalised. */ | |||
static Quat<T> rotate(vec<3,T> const &src, vec<3,T> const &dst); | |||
/* Convert from Euler angles. The axes in fromeuler_xyx are | |||
* x, then y', then x", ie. the axes are attached to the model. | |||
* If you want to rotate around static axes, just reverse the order | |||
* of the arguments. Angle values are in degrees. */ | |||
static Quat<T> fromeuler_xyx(vec<3,T> const &v); | |||
static Quat<T> fromeuler_xzx(vec<3,T> const &v); | |||
static Quat<T> fromeuler_yxy(vec<3,T> const &v); | |||
static Quat<T> fromeuler_yzy(vec<3,T> const &v); | |||
static Quat<T> fromeuler_zxz(vec<3,T> const &v); | |||
static Quat<T> fromeuler_zyz(vec<3,T> const &v); | |||
static Quat<T> fromeuler_xyx(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_xzx(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_yxy(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_yzy(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_zxz(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_zyz(T phi, T theta, T psi); | |||
/* Convert from Tait-Bryan angles (incorrectly called Euler angles, | |||
* but since everyone does it…). The axes in fromeuler_xyz are | |||
* x, then y', then z", ie. the axes are attached to the model. | |||
* If you want to apply yaw around x, pitch around y, and roll | |||
* around z, use fromeuler_xyz. Angle values are in degrees. | |||
* If you want to rotate around static axes, reverse the order in | |||
* the function name (_zyx instead of _xyz) AND reverse the order | |||
* of the arguments. */ | |||
static Quat<T> fromeuler_xyz(vec<3,T> const &v); | |||
static Quat<T> fromeuler_xzy(vec<3,T> const &v); | |||
static Quat<T> fromeuler_yxz(vec<3,T> const &v); | |||
static Quat<T> fromeuler_yzx(vec<3,T> const &v); | |||
static Quat<T> fromeuler_zxy(vec<3,T> const &v); | |||
static Quat<T> fromeuler_zyx(vec<3,T> const &v); | |||
static Quat<T> fromeuler_xyz(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_xzy(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_yxz(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_yzx(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_zxy(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_zyx(T phi, T theta, T psi); | |||
inline Quat<T> operator *(Quat<T> const &val) const; | |||
inline Quat<T> operator *=(Quat<T> const &val) | |||
{ | |||
return *this = (*this) * val; | |||
} | |||
inline Quat<T> operator ~() const | |||
{ | |||
return Quat<T>(w, -x, -y, -z); | |||
} | |||
inline vec<3,T> transform(vec<3,T> const &v) const | |||
{ | |||
Quat<T> p = Quat<T>(0, v.x, v.y, v.z); | |||
Quat<T> q = *this * p / *this; | |||
return vec<3,T>(q.x, q.y, q.z); | |||
} | |||
inline vec<4,T> transform(vec<4,T> const &v) const | |||
{ | |||
Quat<T> p = Quat<T>(0, v.x, v.y, v.z); | |||
Quat<T> q = *this * p / *this; | |||
return vec<4,T>(q.x, q.y, q.z, v.w); | |||
} | |||
inline vec<3,T> operator *(vec<3,T> const &v) const | |||
{ | |||
return transform(v); | |||
} | |||
inline vec<4,T> operator *(vec<4,T> const &v) const | |||
{ | |||
return transform(v); | |||
} | |||
inline vec<3,T> axis() | |||
{ | |||
vec<3,T> v(x, y, z); | |||
T n2 = sqlength(v); | |||
if (n2 <= (T)1e-6) | |||
return vec<3,T>::axis_x; | |||
return normalize(v); | |||
} | |||
inline T angle() | |||
{ | |||
vec<3,T> v(x, y, z); | |||
T n2 = sqlength(v); | |||
if (n2 <= (T)1e-6) | |||
return (T)0; | |||
return (T)2 * lol::atan2(lol::sqrt(n2), w); | |||
} | |||
template<typename U> | |||
friend std::ostream &operator<<(std::ostream &stream, Quat<U> const &v); | |||
/* XXX: storage order is wxyz, unlike vectors! */ | |||
T w, x, y, z; | |||
}; | |||
template<typename T> | |||
static inline T dot(Quat<T> const &q1, Quat<T> const &q2) | |||
{ | |||
T ret(0); | |||
for (size_t i = 0; i < sizeof(Quat<T>) / sizeof(T); ++i) | |||
ret += q1[i] * q2[i]; | |||
return ret; | |||
} | |||
template<typename T> | |||
static inline T sqlength(Quat<T> const &q) | |||
{ | |||
return dot(q, q); | |||
} | |||
template<typename T> | |||
static inline T length(Quat<T> const &q) | |||
{ | |||
/* FIXME: this is not very nice */ | |||
return (T)sqrt((double)sqlength(q)); | |||
} | |||
template<typename T> | |||
static inline T norm(Quat<T> const &q) | |||
{ | |||
return length(q); | |||
} | |||
template<typename T> | |||
static inline Quat<T> re(Quat<T> const &q) | |||
{ | |||
return ~q / sqlength(q); | |||
} | |||
template<typename T> | |||
static inline Quat<T> normalize(Quat<T> const &q) | |||
{ | |||
T norm = (T)length(q); | |||
return norm ? q / norm : Quat<T>(T(0)); | |||
} | |||
template<typename T> | |||
static inline Quat<T> operator /(T x, Quat<T> const &y) | |||
{ | |||
return x * re(y); | |||
} | |||
template<typename T> | |||
static inline Quat<T> operator /(Quat<T> const &x, Quat<T> const &y) | |||
{ | |||
return x * re(y); | |||
} | |||
template<typename T> | |||
extern Quat<T> slerp(Quat<T> const &qa, Quat<T> const &qb, T f); | |||
template<typename T> | |||
inline Quat<T> Quat<T>::operator *(Quat<T> const &val) const | |||
{ | |||
Quat<T> ret; | |||
vec<3,T> v1(x, y, z); | |||
vec<3,T> v2(val.x, val.y, val.z); | |||
vec<3,T> v3 = cross(v1, v2) + w * v2 + val.w * v1; | |||
return Quat<T>(w * val.w - dot(v1, v2), v3.x, v3.y, v3.z); | |||
} | |||
#if !LOL_FEATURE_CXX11_CONSTEXPR | |||
#undef constexpr | |||
#endif | |||
} /* namespace lol */ | |||
#endif // __LOL_MATH_TRANSFORM_H__ | |||
@@ -9,14 +9,13 @@ | |||
// | |||
// | |||
// The vector, complex, quaternion and matrix classes | |||
// -------------------------------------------------- | |||
// The vector classes | |||
// ------------------ | |||
// | |||
#if !defined __LOL_MATH_VECTOR_H__ | |||
#define __LOL_MATH_VECTOR_H__ | |||
#include <stdint.h> | |||
#include <ostream> | |||
#include <lol/math/half.h> | |||
@@ -49,7 +48,7 @@ namespace lol | |||
* fuck it. | |||
*/ | |||
template<int N, typename T, int MASK = -1> | |||
template<int N, typename T, int MASK> | |||
struct vec | |||
{ | |||
typedef vec<N,T> type; | |||
@@ -59,6 +58,7 @@ struct vec | |||
#if LOL_FEATURE_CXX11_RELAXED_UNIONS | |||
inline vec<N, T, MASK>& operator =(vec<N, T, MASK> const &that) | |||
{ | |||
/* Pass by value in case this == &that */ | |||
return *this = (vec<N,T>)that; | |||
} | |||
#endif | |||
@@ -89,81 +89,6 @@ private: | |||
T m_data[N]; | |||
}; | |||
/* The generic complex and quaternion types. */ | |||
template<typename T> struct Cmplx; | |||
template<typename T> struct Quat; | |||
/* | |||
* Generic GLSL-like type names | |||
*/ | |||
#define COMMA , | |||
#define LOL_VECTOR_TYPEDEFS(tleft, tright, suffix) \ | |||
typedef tleft half tright f16##suffix; \ | |||
typedef tleft float tright suffix; \ | |||
typedef tleft double tright d##suffix; \ | |||
typedef tleft ldouble tright f128##suffix; \ | |||
typedef tleft int8_t tright i8##suffix; \ | |||
typedef tleft uint8_t tright u8##suffix; \ | |||
typedef tleft int16_t tright i16##suffix; \ | |||
typedef tleft uint16_t tright u16##suffix; \ | |||
typedef tleft int32_t tright i##suffix; \ | |||
typedef tleft uint32_t tright u##suffix; \ | |||
typedef tleft int64_t tright i64##suffix; \ | |||
typedef tleft uint64_t tright u64##suffix; \ | |||
typedef tleft real tright r##suffix; | |||
LOL_VECTOR_TYPEDEFS(vec<2 COMMA, >, vec2) | |||
LOL_VECTOR_TYPEDEFS(vec<3 COMMA, >, vec3) | |||
LOL_VECTOR_TYPEDEFS(vec<4 COMMA, >, vec4) | |||
LOL_VECTOR_TYPEDEFS(matrix<2 COMMA 2 COMMA, >, mat2) | |||
LOL_VECTOR_TYPEDEFS(matrix<3 COMMA 3 COMMA, >, mat3) | |||
LOL_VECTOR_TYPEDEFS(matrix<4 COMMA 4 COMMA, >, mat4) | |||
LOL_VECTOR_TYPEDEFS(matrix<2 COMMA 3 COMMA, >, mat2x3) | |||
LOL_VECTOR_TYPEDEFS(matrix<2 COMMA 4 COMMA, >, mat2x4) | |||
LOL_VECTOR_TYPEDEFS(matrix<3 COMMA 2 COMMA, >, mat3x2) | |||
LOL_VECTOR_TYPEDEFS(matrix<3 COMMA 4 COMMA, >, mat3x4) | |||
LOL_VECTOR_TYPEDEFS(matrix<4 COMMA 2 COMMA, >, mat4x2) | |||
LOL_VECTOR_TYPEDEFS(matrix<4 COMMA 3 COMMA, >, mat4x3) | |||
LOL_VECTOR_TYPEDEFS(Cmplx<, >, cmplx) | |||
LOL_VECTOR_TYPEDEFS(Quat<, >, quat) | |||
#undef LOL_VECTOR_TYPEDEFS | |||
#undef COMMA | |||
/* | |||
* HLSL/Cg-compliant type names. | |||
*/ | |||
typedef vec2 float2; | |||
typedef vec3 float3; | |||
typedef vec4 float4; | |||
typedef mat2 float2x2; | |||
typedef mat3 float3x3; | |||
typedef mat4 float4x4; | |||
typedef mat2x3 float2x3; | |||
typedef mat2x4 float2x4; | |||
typedef mat3x2 float3x2; | |||
typedef mat3x4 float3x4; | |||
typedef mat4x2 float4x2; | |||
typedef mat4x3 float4x3; | |||
typedef ivec2 int2; | |||
typedef ivec3 int3; | |||
typedef ivec4 int4; | |||
typedef imat2 int2x2; | |||
typedef imat3 int3x3; | |||
typedef imat4 int4x4; | |||
typedef imat2x3 int2x3; | |||
typedef imat2x4 int2x4; | |||
typedef imat3x2 int3x2; | |||
typedef imat3x4 int3x4; | |||
typedef imat4x2 int4x2; | |||
typedef imat4x3 int4x3; | |||
/* | |||
* Helper macros for vector type member functions | |||
*/ | |||
@@ -384,117 +309,6 @@ struct vec<2,T> : base_vec2<T> | |||
friend std::ostream &operator<<(std::ostream &stream, vec<2,U> const &v); | |||
}; | |||
/* | |||
* 2-element complexes | |||
*/ | |||
template <typename T> struct Cmplx | |||
{ | |||
typedef Cmplx<T> type; | |||
inline constexpr Cmplx() {} | |||
inline constexpr Cmplx(T X) : x(X), y(T(0)) {} | |||
inline constexpr Cmplx(T X, T Y) : x(X), y(Y) {} | |||
template<typename U> | |||
explicit inline constexpr Cmplx(Cmplx<U> const &z) | |||
: x(z.x), y(z.y) {} | |||
LOL_COMMON_MEMBER_OPS(x) | |||
LOL_NONVECTOR_MEMBER_OPS() | |||
inline Cmplx<T> operator *(Cmplx<T> const &val) const | |||
{ | |||
return Cmplx<T>(x * val.x - y * val.y, x * val.y + y * val.x); | |||
} | |||
inline Cmplx<T> operator *=(Cmplx<T> const &val) | |||
{ | |||
return *this = (*this) * val; | |||
} | |||
inline Cmplx<T> operator ~() const | |||
{ | |||
return Cmplx<T>(x, -y); | |||
} | |||
template<typename U> | |||
friend std::ostream &operator<<(std::ostream &stream, Cmplx<U> const &v); | |||
T x, y; | |||
}; | |||
template<typename T> | |||
static inline T dot(Cmplx<T> const &z1, Cmplx<T> const &z2) | |||
{ | |||
T ret(0); | |||
for (size_t i = 0; i < sizeof(Cmplx<T>) / sizeof(T); ++i) | |||
ret += z1[i] * z2[i]; | |||
return ret; | |||
} | |||
template<typename T> | |||
static inline T sqlength(Cmplx<T> const &z) | |||
{ | |||
return dot(z, z); | |||
} | |||
template<typename T> | |||
static inline T length(Cmplx<T> const &z) | |||
{ | |||
/* FIXME: this is not very nice */ | |||
return (T)sqrt((double)sqlength(z)); | |||
} | |||
template<typename T> | |||
static inline T norm(Cmplx<T> const &z) | |||
{ | |||
return length(z); | |||
} | |||
template<typename T> | |||
static inline Cmplx<T> re(Cmplx<T> const &z) | |||
{ | |||
return ~z / sqlength(z); | |||
} | |||
template<typename T> | |||
static inline Cmplx<T> normalize(Cmplx<T> const &z) | |||
{ | |||
T norm = (T)length(z); | |||
return norm ? z / norm : Cmplx<T>(T(0)); | |||
} | |||
template<typename T> | |||
static inline Cmplx<T> operator /(T a, Cmplx<T> const &b) | |||
{ | |||
return a * re(b); | |||
} | |||
template<typename T> | |||
static inline Cmplx<T> operator /(Cmplx<T> a, Cmplx<T> const &b) | |||
{ | |||
return a * re(b); | |||
} | |||
template<typename T> | |||
static inline bool operator ==(Cmplx<T> const &a, T b) | |||
{ | |||
return (a.x == b) && !a.y; | |||
} | |||
template<typename T> | |||
static inline bool operator !=(Cmplx<T> const &a, T b) | |||
{ | |||
return (a.x != b) || a.y; | |||
} | |||
template<typename T> | |||
static inline bool operator ==(T a, Cmplx<T> const &b) { return b == a; } | |||
template<typename T> | |||
static inline bool operator !=(T a, Cmplx<T> const &b) { return b != a; } | |||
/* | |||
* 3-element vectors | |||
*/ | |||
@@ -1140,205 +954,6 @@ struct vec<4,T> : base_vec4<T> | |||
friend std::ostream &operator<<(std::ostream &stream, vec<4,U> const &v); | |||
}; | |||
/* | |||
* 4-element quaternions | |||
*/ | |||
template <typename T> struct Quat | |||
{ | |||
typedef Quat<T> type; | |||
inline constexpr Quat() {} | |||
inline constexpr Quat(T W) : w(W), x(0), y(0), z(0) {} | |||
inline constexpr Quat(T W, T X, T Y, T Z) : w(W), x(X), y(Y), z(Z) {} | |||
template<typename U> | |||
explicit inline constexpr Quat(Quat<U> const &q) | |||
: w(q.w), x(q.x), y(q.y), z(q.z) {} | |||
Quat(matrix<3,3,T> const &m); | |||
Quat(matrix<4,4,T> const &m); | |||
LOL_COMMON_MEMBER_OPS(w) | |||
LOL_NONVECTOR_MEMBER_OPS() | |||
/* Create a unit quaternion representing a rotation around an axis. */ | |||
static Quat<T> rotate(T degrees, T x, T y, T z); | |||
static Quat<T> rotate(T degrees, vec<3,T> const &v); | |||
/* Create a unit quaternion representing a rotation between two vectors. | |||
* Input vectors need not be normalised. */ | |||
static Quat<T> rotate(vec<3,T> const &src, vec<3,T> const &dst); | |||
/* Convert from Euler angles. The axes in fromeuler_xyx are | |||
* x, then y', then x", ie. the axes are attached to the model. | |||
* If you want to rotate around static axes, just reverse the order | |||
* of the arguments. Angle values are in degrees. */ | |||
static Quat<T> fromeuler_xyx(vec<3,T> const &v); | |||
static Quat<T> fromeuler_xzx(vec<3,T> const &v); | |||
static Quat<T> fromeuler_yxy(vec<3,T> const &v); | |||
static Quat<T> fromeuler_yzy(vec<3,T> const &v); | |||
static Quat<T> fromeuler_zxz(vec<3,T> const &v); | |||
static Quat<T> fromeuler_zyz(vec<3,T> const &v); | |||
static Quat<T> fromeuler_xyx(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_xzx(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_yxy(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_yzy(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_zxz(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_zyz(T phi, T theta, T psi); | |||
/* Convert from Tait-Bryan angles (incorrectly called Euler angles, | |||
* but since everyone does it…). The axes in fromeuler_xyz are | |||
* x, then y', then z", ie. the axes are attached to the model. | |||
* If you want to apply yaw around x, pitch around y, and roll | |||
* around z, use fromeuler_xyz. Angle values are in degrees. | |||
* If you want to rotate around static axes, reverse the order in | |||
* the function name (_zyx instead of _xyz) AND reverse the order | |||
* of the arguments. */ | |||
static Quat<T> fromeuler_xyz(vec<3,T> const &v); | |||
static Quat<T> fromeuler_xzy(vec<3,T> const &v); | |||
static Quat<T> fromeuler_yxz(vec<3,T> const &v); | |||
static Quat<T> fromeuler_yzx(vec<3,T> const &v); | |||
static Quat<T> fromeuler_zxy(vec<3,T> const &v); | |||
static Quat<T> fromeuler_zyx(vec<3,T> const &v); | |||
static Quat<T> fromeuler_xyz(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_xzy(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_yxz(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_yzx(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_zxy(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_zyx(T phi, T theta, T psi); | |||
inline Quat<T> operator *(Quat<T> const &val) const; | |||
inline Quat<T> operator *=(Quat<T> const &val) | |||
{ | |||
return *this = (*this) * val; | |||
} | |||
inline Quat<T> operator ~() const | |||
{ | |||
return Quat<T>(w, -x, -y, -z); | |||
} | |||
inline vec<3,T> transform(vec<3,T> const &v) const | |||
{ | |||
Quat<T> p = Quat<T>(0, v.x, v.y, v.z); | |||
Quat<T> q = *this * p / *this; | |||
return vec<3,T>(q.x, q.y, q.z); | |||
} | |||
inline vec<4,T> transform(vec<4,T> const &v) const | |||
{ | |||
Quat<T> p = Quat<T>(0, v.x, v.y, v.z); | |||
Quat<T> q = *this * p / *this; | |||
return vec<4,T>(q.x, q.y, q.z, v.w); | |||
} | |||
inline vec<3,T> operator *(vec<3,T> const &v) const | |||
{ | |||
return transform(v); | |||
} | |||
inline vec<4,T> operator *(vec<4,T> const &v) const | |||
{ | |||
return transform(v); | |||
} | |||
inline vec<3,T> axis() | |||
{ | |||
vec<3,T> v(x, y, z); | |||
T n2 = sqlength(v); | |||
if (n2 <= (T)1e-6) | |||
return vec<3,T>::axis_x; | |||
return normalize(v); | |||
} | |||
inline T angle() | |||
{ | |||
vec<3,T> v(x, y, z); | |||
T n2 = sqlength(v); | |||
if (n2 <= (T)1e-6) | |||
return (T)0; | |||
return (T)2 * lol::atan2(lol::sqrt(n2), w); | |||
} | |||
template<typename U> | |||
friend std::ostream &operator<<(std::ostream &stream, Quat<U> const &v); | |||
/* XXX: storage order is wxyz, unlike vectors! */ | |||
T w, x, y, z; | |||
}; | |||
template<typename T> | |||
static inline T dot(Quat<T> const &q1, Quat<T> const &q2) | |||
{ | |||
T ret(0); | |||
for (size_t i = 0; i < sizeof(Quat<T>) / sizeof(T); ++i) | |||
ret += q1[i] * q2[i]; | |||
return ret; | |||
} | |||
template<typename T> | |||
static inline T sqlength(Quat<T> const &q) | |||
{ | |||
return dot(q, q); | |||
} | |||
template<typename T> | |||
static inline T length(Quat<T> const &q) | |||
{ | |||
/* FIXME: this is not very nice */ | |||
return (T)sqrt((double)sqlength(q)); | |||
} | |||
template<typename T> | |||
static inline T norm(Quat<T> const &q) | |||
{ | |||
return length(q); | |||
} | |||
template<typename T> | |||
static inline Quat<T> re(Quat<T> const &q) | |||
{ | |||
return ~q / sqlength(q); | |||
} | |||
template<typename T> | |||
static inline Quat<T> normalize(Quat<T> const &q) | |||
{ | |||
T norm = (T)length(q); | |||
return norm ? q / norm : Quat<T>(T(0)); | |||
} | |||
template<typename T> | |||
static inline Quat<T> operator /(T x, Quat<T> const &y) | |||
{ | |||
return x * re(y); | |||
} | |||
template<typename T> | |||
static inline Quat<T> operator /(Quat<T> const &x, Quat<T> const &y) | |||
{ | |||
return x * re(y); | |||
} | |||
template<typename T> | |||
extern Quat<T> slerp(Quat<T> const &qa, Quat<T> const &qb, T f); | |||
/* | |||
* Clean up our ugly macros. | |||
*/ | |||
#undef LOL_COMMON_MEMBER_OPS | |||
#undef LOL_VECTOR_MEMBER_OPS | |||
#undef LOL_NONVECTOR_MEMBER_OPS | |||
#undef LOL_V_VV_OP | |||
#undef LOL_V_VV_ASSIGN_OP | |||
#undef LOL_V_VS_OP | |||
#undef LOL_V_VS_ASSIGN_OP | |||
#undef LOL_B_VV_OP | |||
/* | |||
* Operators for swizzled vectors. Since template deduction cannot be | |||
* done for two arbitrary vec<> values, we help the compiler understand | |||
@@ -1583,20 +1198,6 @@ static inline vec<N,T> radians(vec<N,T,MASK> const &a) | |||
return ret; | |||
} | |||
/* | |||
* Definition of additional functions requiring vector functions | |||
*/ | |||
template<typename T> | |||
inline Quat<T> Quat<T>::operator *(Quat<T> const &val) const | |||
{ | |||
Quat<T> ret; | |||
vec<3,T> v1(x, y, z); | |||
vec<3,T> v2(val.x, val.y, val.z); | |||
vec<3,T> v3 = cross(v1, v2) + w * v2 + val.w * v1; | |||
return Quat<T>(w * val.w - dot(v1, v2), v3.x, v3.y, v3.z); | |||
} | |||
/* | |||
* Magic vector swizzling (part 2/2) | |||
*/ | |||
@@ -330,6 +330,7 @@ | |||
<ClInclude Include="lol\math\rand.h" /> | |||
<ClInclude Include="lol\math\real.h" /> | |||
<ClInclude Include="lol\math\remez.h" /> | |||
<ClInclude Include="lol\math\transform.h" /> | |||
<ClInclude Include="lol\math\vector.h" /> | |||
<ClInclude Include="lol\sys\all.h" /> | |||
<ClInclude Include="lol\sys\file.h" /> | |||
@@ -450,6 +450,9 @@ | |||
<ClInclude Include="lol\math\remez.h"> | |||
<Filter>lol\math</Filter> | |||
</ClInclude> | |||
<ClInclude Include="lol\math\transform.h"> | |||
<Filter>lol\math</Filter> | |||
</ClInclude> | |||
<ClInclude Include="lol\math\vector.h"> | |||
<Filter>lol\math</Filter> | |||
</ClInclude> | |||