diff --git a/src/Makefile.am b/src/Makefile.am index a6fda3e6..6d2641d5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 \ diff --git a/src/lol/base/types.h b/src/lol/base/types.h index 5c24fc43..0d932487 100644 --- a/src/lol/base/types.h +++ b/src/lol/base/types.h @@ -11,6 +11,8 @@ #if !defined __LOL_BASE_TYPES_H__ #define __LOL_BASE_TYPES_H__ +#include + 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 struct vec; +/* + * Forward declaration of vec and matrix + */ + +template struct vec; template struct matrix; +template struct Cmplx; +template 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 */ diff --git a/src/lol/math/all.h b/src/lol/math/all.h index 446901a9..69b72c14 100644 --- a/src/lol/math/all.h +++ b/src/lol/math/all.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include diff --git a/src/lol/math/matrix.h b/src/lol/math/matrix.h index 863e37e7..bb2b5c8f 100644 --- a/src/lol/math/matrix.h +++ b/src/lol/math/matrix.h @@ -16,10 +16,10 @@ #if !defined __LOL_MATH_MATRIX_H__ #define __LOL_MATH_MATRIX_H__ -#include #include #include +#include namespace lol { diff --git a/src/lol/math/transform.h b/src/lol/math/transform.h new file mode 100644 index 00000000..a275fcd4 --- /dev/null +++ b/src/lol/math/transform.h @@ -0,0 +1,344 @@ +// +// Lol Engine +// +// Copyright: (c) 2010-2014 Sam Hocevar +// 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 + +#include +#include + +namespace lol +{ + +#if !LOL_FEATURE_CXX11_CONSTEXPR +# define constexpr /* */ +#endif + +/* + * 2-element complexes + */ + +template struct Cmplx +{ + typedef Cmplx 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 + explicit inline constexpr Cmplx(Cmplx const &z) + : x(z.x), y(z.y) {} + + LOL_COMMON_MEMBER_OPS(x) + LOL_NONVECTOR_MEMBER_OPS() + + inline Cmplx operator *(Cmplx const &val) const + { + return Cmplx(x * val.x - y * val.y, x * val.y + y * val.x); + } + + inline Cmplx operator *=(Cmplx const &val) + { + return *this = (*this) * val; + } + + inline Cmplx operator ~() const + { + return Cmplx(x, -y); + } + + template + friend std::ostream &operator<<(std::ostream &stream, Cmplx const &v); + + T x, y; +}; + +template +static inline T dot(Cmplx const &z1, Cmplx const &z2) +{ + T ret(0); + for (size_t i = 0; i < sizeof(Cmplx) / sizeof(T); ++i) + ret += z1[i] * z2[i]; + return ret; +} + +template +static inline T sqlength(Cmplx const &z) +{ + return dot(z, z); +} + +template +static inline T length(Cmplx const &z) +{ + /* FIXME: this is not very nice */ + return (T)sqrt((double)sqlength(z)); +} + +template +static inline T norm(Cmplx const &z) +{ + return length(z); +} + +template +static inline Cmplx re(Cmplx const &z) +{ + return ~z / sqlength(z); +} + +template +static inline Cmplx normalize(Cmplx const &z) +{ + T norm = (T)length(z); + return norm ? z / norm : Cmplx(T(0)); +} + +template +static inline Cmplx operator /(T a, Cmplx const &b) +{ + return a * re(b); +} + +template +static inline Cmplx operator /(Cmplx a, Cmplx const &b) +{ + return a * re(b); +} + +template +static inline bool operator ==(Cmplx const &a, T b) +{ + return (a.x == b) && !a.y; +} + +template +static inline bool operator !=(Cmplx const &a, T b) +{ + return (a.x != b) || a.y; +} + +template +static inline bool operator ==(T a, Cmplx const &b) { return b == a; } + +template +static inline bool operator !=(T a, Cmplx const &b) { return b != a; } + +/* + * 4-element quaternions + */ + +template struct Quat +{ + typedef Quat 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 + explicit inline constexpr Quat(Quat 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 rotate(T degrees, T x, T y, T z); + static Quat 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 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 fromeuler_xyx(vec<3,T> const &v); + static Quat fromeuler_xzx(vec<3,T> const &v); + static Quat fromeuler_yxy(vec<3,T> const &v); + static Quat fromeuler_yzy(vec<3,T> const &v); + static Quat fromeuler_zxz(vec<3,T> const &v); + static Quat fromeuler_zyz(vec<3,T> const &v); + static Quat fromeuler_xyx(T phi, T theta, T psi); + static Quat fromeuler_xzx(T phi, T theta, T psi); + static Quat fromeuler_yxy(T phi, T theta, T psi); + static Quat fromeuler_yzy(T phi, T theta, T psi); + static Quat fromeuler_zxz(T phi, T theta, T psi); + static Quat 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 fromeuler_xyz(vec<3,T> const &v); + static Quat fromeuler_xzy(vec<3,T> const &v); + static Quat fromeuler_yxz(vec<3,T> const &v); + static Quat fromeuler_yzx(vec<3,T> const &v); + static Quat fromeuler_zxy(vec<3,T> const &v); + static Quat fromeuler_zyx(vec<3,T> const &v); + static Quat fromeuler_xyz(T phi, T theta, T psi); + static Quat fromeuler_xzy(T phi, T theta, T psi); + static Quat fromeuler_yxz(T phi, T theta, T psi); + static Quat fromeuler_yzx(T phi, T theta, T psi); + static Quat fromeuler_zxy(T phi, T theta, T psi); + static Quat fromeuler_zyx(T phi, T theta, T psi); + + inline Quat operator *(Quat const &val) const; + + inline Quat operator *=(Quat const &val) + { + return *this = (*this) * val; + } + + inline Quat operator ~() const + { + return Quat(w, -x, -y, -z); + } + + inline vec<3,T> transform(vec<3,T> const &v) const + { + Quat p = Quat(0, v.x, v.y, v.z); + Quat 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 p = Quat(0, v.x, v.y, v.z); + Quat 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 + friend std::ostream &operator<<(std::ostream &stream, Quat const &v); + + /* XXX: storage order is wxyz, unlike vectors! */ + T w, x, y, z; +}; + +template +static inline T dot(Quat const &q1, Quat const &q2) +{ + T ret(0); + for (size_t i = 0; i < sizeof(Quat) / sizeof(T); ++i) + ret += q1[i] * q2[i]; + return ret; +} + +template +static inline T sqlength(Quat const &q) +{ + return dot(q, q); +} + +template +static inline T length(Quat const &q) +{ + /* FIXME: this is not very nice */ + return (T)sqrt((double)sqlength(q)); +} + +template +static inline T norm(Quat const &q) +{ + return length(q); +} + +template +static inline Quat re(Quat const &q) +{ + return ~q / sqlength(q); +} + +template +static inline Quat normalize(Quat const &q) +{ + T norm = (T)length(q); + return norm ? q / norm : Quat(T(0)); +} + +template +static inline Quat operator /(T x, Quat const &y) +{ + return x * re(y); +} + +template +static inline Quat operator /(Quat const &x, Quat const &y) +{ + return x * re(y); +} + +template +extern Quat slerp(Quat const &qa, Quat const &qb, T f); + +template +inline Quat Quat::operator *(Quat const &val) const +{ + Quat 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(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__ + diff --git a/src/lol/math/vector.h b/src/lol/math/vector.h index cc799578..dfdce022 100644 --- a/src/lol/math/vector.h +++ b/src/lol/math/vector.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 #include #include @@ -49,7 +48,7 @@ namespace lol * fuck it. */ -template +template struct vec { typedef vec type; @@ -59,6 +58,7 @@ struct vec #if LOL_FEATURE_CXX11_RELAXED_UNIONS inline vec& operator =(vec const &that) { + /* Pass by value in case this == &that */ return *this = (vec)that; } #endif @@ -89,81 +89,6 @@ private: T m_data[N]; }; -/* The generic complex and quaternion types. */ -template struct Cmplx; -template 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 friend std::ostream &operator<<(std::ostream &stream, vec<2,U> const &v); }; -/* - * 2-element complexes - */ - -template struct Cmplx -{ - typedef Cmplx 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 - explicit inline constexpr Cmplx(Cmplx const &z) - : x(z.x), y(z.y) {} - - LOL_COMMON_MEMBER_OPS(x) - LOL_NONVECTOR_MEMBER_OPS() - - inline Cmplx operator *(Cmplx const &val) const - { - return Cmplx(x * val.x - y * val.y, x * val.y + y * val.x); - } - - inline Cmplx operator *=(Cmplx const &val) - { - return *this = (*this) * val; - } - - inline Cmplx operator ~() const - { - return Cmplx(x, -y); - } - - template - friend std::ostream &operator<<(std::ostream &stream, Cmplx const &v); - - T x, y; -}; - -template -static inline T dot(Cmplx const &z1, Cmplx const &z2) -{ - T ret(0); - for (size_t i = 0; i < sizeof(Cmplx) / sizeof(T); ++i) - ret += z1[i] * z2[i]; - return ret; -} - -template -static inline T sqlength(Cmplx const &z) -{ - return dot(z, z); -} - -template -static inline T length(Cmplx const &z) -{ - /* FIXME: this is not very nice */ - return (T)sqrt((double)sqlength(z)); -} - -template -static inline T norm(Cmplx const &z) -{ - return length(z); -} - -template -static inline Cmplx re(Cmplx const &z) -{ - return ~z / sqlength(z); -} - -template -static inline Cmplx normalize(Cmplx const &z) -{ - T norm = (T)length(z); - return norm ? z / norm : Cmplx(T(0)); -} - -template -static inline Cmplx operator /(T a, Cmplx const &b) -{ - return a * re(b); -} - -template -static inline Cmplx operator /(Cmplx a, Cmplx const &b) -{ - return a * re(b); -} - -template -static inline bool operator ==(Cmplx const &a, T b) -{ - return (a.x == b) && !a.y; -} - -template -static inline bool operator !=(Cmplx const &a, T b) -{ - return (a.x != b) || a.y; -} - -template -static inline bool operator ==(T a, Cmplx const &b) { return b == a; } - -template -static inline bool operator !=(T a, Cmplx const &b) { return b != a; } - /* * 3-element vectors */ @@ -1140,205 +954,6 @@ struct vec<4,T> : base_vec4 friend std::ostream &operator<<(std::ostream &stream, vec<4,U> const &v); }; -/* - * 4-element quaternions - */ - -template struct Quat -{ - typedef Quat 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 - explicit inline constexpr Quat(Quat 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 rotate(T degrees, T x, T y, T z); - static Quat 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 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 fromeuler_xyx(vec<3,T> const &v); - static Quat fromeuler_xzx(vec<3,T> const &v); - static Quat fromeuler_yxy(vec<3,T> const &v); - static Quat fromeuler_yzy(vec<3,T> const &v); - static Quat fromeuler_zxz(vec<3,T> const &v); - static Quat fromeuler_zyz(vec<3,T> const &v); - static Quat fromeuler_xyx(T phi, T theta, T psi); - static Quat fromeuler_xzx(T phi, T theta, T psi); - static Quat fromeuler_yxy(T phi, T theta, T psi); - static Quat fromeuler_yzy(T phi, T theta, T psi); - static Quat fromeuler_zxz(T phi, T theta, T psi); - static Quat 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 fromeuler_xyz(vec<3,T> const &v); - static Quat fromeuler_xzy(vec<3,T> const &v); - static Quat fromeuler_yxz(vec<3,T> const &v); - static Quat fromeuler_yzx(vec<3,T> const &v); - static Quat fromeuler_zxy(vec<3,T> const &v); - static Quat fromeuler_zyx(vec<3,T> const &v); - static Quat fromeuler_xyz(T phi, T theta, T psi); - static Quat fromeuler_xzy(T phi, T theta, T psi); - static Quat fromeuler_yxz(T phi, T theta, T psi); - static Quat fromeuler_yzx(T phi, T theta, T psi); - static Quat fromeuler_zxy(T phi, T theta, T psi); - static Quat fromeuler_zyx(T phi, T theta, T psi); - - inline Quat operator *(Quat const &val) const; - - inline Quat operator *=(Quat const &val) - { - return *this = (*this) * val; - } - - inline Quat operator ~() const - { - return Quat(w, -x, -y, -z); - } - - inline vec<3,T> transform(vec<3,T> const &v) const - { - Quat p = Quat(0, v.x, v.y, v.z); - Quat 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 p = Quat(0, v.x, v.y, v.z); - Quat 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 - friend std::ostream &operator<<(std::ostream &stream, Quat const &v); - - /* XXX: storage order is wxyz, unlike vectors! */ - T w, x, y, z; -}; - -template -static inline T dot(Quat const &q1, Quat const &q2) -{ - T ret(0); - for (size_t i = 0; i < sizeof(Quat) / sizeof(T); ++i) - ret += q1[i] * q2[i]; - return ret; -} - -template -static inline T sqlength(Quat const &q) -{ - return dot(q, q); -} - -template -static inline T length(Quat const &q) -{ - /* FIXME: this is not very nice */ - return (T)sqrt((double)sqlength(q)); -} - -template -static inline T norm(Quat const &q) -{ - return length(q); -} - -template -static inline Quat re(Quat const &q) -{ - return ~q / sqlength(q); -} - -template -static inline Quat normalize(Quat const &q) -{ - T norm = (T)length(q); - return norm ? q / norm : Quat(T(0)); -} - -template -static inline Quat operator /(T x, Quat const &y) -{ - return x * re(y); -} - -template -static inline Quat operator /(Quat const &x, Quat const &y) -{ - return x * re(y); -} - -template -extern Quat slerp(Quat const &qa, Quat 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 radians(vec const &a) return ret; } -/* - * Definition of additional functions requiring vector functions - */ - -template -inline Quat Quat::operator *(Quat const &val) const -{ - Quat 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(w * val.w - dot(v1, v2), v3.x, v3.y, v3.z); -} - /* * Magic vector swizzling (part 2/2) */ diff --git a/src/lolcore.vcxproj b/src/lolcore.vcxproj index dd1e4100..b02b0c0d 100644 --- a/src/lolcore.vcxproj +++ b/src/lolcore.vcxproj @@ -330,6 +330,7 @@ + diff --git a/src/lolcore.vcxproj.filters b/src/lolcore.vcxproj.filters index 6849a1c8..8185f8dc 100644 --- a/src/lolcore.vcxproj.filters +++ b/src/lolcore.vcxproj.filters @@ -450,6 +450,9 @@ lol\math + + lol\math + lol\math