Просмотр исходного кода

math: move complex/quaternion code out of vector.h and into transform.h.

undefined
Sam Hocevar 10 лет назад
Родитель
Сommit
a6327b2469
8 измененных файлов: 437 добавлений и 406 удалений
  1. +1
    -0
      src/Makefile.am
  2. +82
    -2
      src/lol/base/types.h
  3. +1
    -0
      src/lol/math/all.h
  4. +1
    -1
      src/lol/math/matrix.h
  5. +344
    -0
      src/lol/math/transform.h
  6. +4
    -403
      src/lol/math/vector.h
  7. +1
    -0
      src/lolcore.vcxproj
  8. +3
    -0
      src/lolcore.vcxproj.filters

+ 1
- 0
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 \


+ 82
- 2
src/lol/base/types.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 */



+ 1
- 0
src/lol/math/all.h Просмотреть файл

@@ -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>


+ 1
- 1
src/lol/math/matrix.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
{


+ 344
- 0
src/lol/math/transform.h Просмотреть файл

@@ -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__


+ 4
- 403
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 <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)
*/


+ 1
- 0
src/lolcore.vcxproj Просмотреть файл

@@ -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" />


+ 3
- 0
src/lolcore.vcxproj.filters Просмотреть файл

@@ -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>


Загрузка…
Отмена
Сохранить