AngryDude
 All Classes Namespaces Files Functions Variables Macros
DualQuaternion.hpp
Go to the documentation of this file.
1 #ifndef __DualQuaternion_hpp__
2 #define __DualQuaternion_hpp__
3 
4 #include <cmath>
5 #include <type_traits>
6 
23 {
24 public:
25  Quaternion() = default;
26  Quaternion(float x, float y, float z, float w): x(x), y(y), z(z), w(w) {}
27 
30  template <typename Q,
31  typename std::enable_if<not std::is_floating_point<Q>::value>::type* = nullptr>
32  Quaternion(const Q& q): x(q.x), y(q.y), z(q.z), w(q.w) {}
33 
40  template <typename F,
41  typename std::enable_if<std::is_floating_point<F>::value>::type* = nullptr>
42  Quaternion(F f): x(0.f), y(0.f), z(0.f), w(f) {}
43 
45  template <typename V3>
46  Quaternion(const V3& unitAxis, float thetaRadians)
47  {
48  const float halfAngle = thetaRadians / 2.f;
49  const float sa = std::sin(halfAngle);
50  const float ca = std::cos(halfAngle);
51  x = sa*unitAxis.x;
52  y = sa*unitAxis.y;
53  z = sa*unitAxis.z;
54  w = ca;
55  }
56 
59  static const Quaternion identity()
60  {
61  return Quaternion(0.f, 0.f, 0.f, 1.f);
62  }
63 
67  template <typename V3>
68  static const V3 toVector(const Quaternion& q)
69  {
70  return V3(q.x, q.y, q.z);
71  }
72 
74  template <typename V3>
75  static const Quaternion fromVector(const V3& v)
76  {
77  return Quaternion(v.x, v.y, v.z, 0.f);
78  }
79 
83  template <typename M3>
84  static const M3 toMatrix(const Quaternion& q)
85  {
86  const float x = q.x;
87  const float y = q.y;
88  const float z = q.z;
89  const float w = q.w;
90  M3 m;
91  m(0,0) = 1.f - 2.f*(y*y + z*z);
92  m(0,1) = 2.f*(x*y - w*z);
93  m(0,2) = 2.f*(x*z + w*y);
94 
95  m(1,0) = 2.f*(x*y + w*z);
96  m(1,1) = 1.f - 2.f*(x*x + z*z);
97  m(1,2) = 2.f*(y*z - w*x);
98 
99  m(2,0) = 2.f*(x*z - w*y);
100  m(2,1) = 2.f*(y*z + w*x);
101  m(2,2) = 1.f - 2.f*(x*x + y*y);
102  return m;
103  }
104 
108  template <typename M3>
109  static const Quaternion fromMatrix(const M3& m)
110  {
111  Quaternion q;
112  const float trace = m(0,0) + m(1,1) + m(2,2);
113  if (trace > 0.f) {
114  const float s = std::sqrt(trace + 1.f) * 2.f;
115  q.w = 0.25f * s;
116  q.x = (m(2,1) - m(1,2)) / s;
117  q.y = (m(0,2) - m(2,0)) / s;
118  q.z = (m(1,0) - m(0,1)) / s;
119  } else if ((m(0,0) > m(1,1)) && (m(0,0) > m(2,2))) {
120  const float s = std::sqrt(m(0,0) - m(1,1) - m(2,2) + 1.f) * 2.f;
121  q.w = (m(2,1) - m(1,2)) / s;
122  q.x = 0.25f * s;
123  q.y = (m(0,1) + m(1,0)) / s;
124  q.z = (m(0,2) + m(2,0)) / s;
125  } else if (m(1,1) > m(2,2)) {
126  const float s = std::sqrt(m(1,1) - m(0,0) - m(2,2) + 1.f) * 2.f;
127  q.w = (m(0,2) - m(2,0)) / s;
128  q.x = (m(0,1) + m(1,0)) / s;
129  q.y = 0.25f * s;
130  q.z = (m(1,2) + m(2,1)) / s;
131  } else {
132  const float s = std::sqrt(m(2,2) - m(0,0) - m(1,1) + 1.f) * 2.f;
133  q.w = (m(1,0) - m(0,1)) / s;
134  q.x = (m(0,2) + m(2,0)) / s;
135  q.y = (m(1,2) + m(2,1)) / s;
136  q.z = 0.25f * s;
137  }
138  return q;
139  }
140 
141  float x,y,z;
142 
144  float w;
145 };
146 
148 inline const Quaternion operator + (const Quaternion& a, const Quaternion& b)
149 {
150  return Quaternion(a.x + b.x,
151  a.y + b.y,
152  a.z + b.z,
153  a.w + b.w);
154 }
155 
157 inline const Quaternion operator * (const Quaternion& a, const Quaternion& b)
158 {
159  return Quaternion(a.y*b.z - a.z*b.y + a.w*b.x + a.x*b.w,
160  a.z*b.x - a.x*b.z + a.w*b.y + a.y*b.w,
161  a.x*b.y - a.y*b.x + a.w*b.z + a.z*b.w,
162  a.w*b.w - a.x*b.x - a.y*b.y - a.z*b.z);
163 }
164 
165 inline const Quaternion conjugate(const Quaternion& q)
166 {
167  return Quaternion(-q.x, -q.y, -q.z, q.w);
168 }
169 
171 {
172 public:
173  DualQuaternion() = default;
175  real(real), dual(dual) {}
176 
177  template <typename V3>
178  DualQuaternion(const V3& translation, const Quaternion& rotation)
179  {
181  real = rotation;
182  dual = Quaternion(translation.x / 2.f, translation.y / 2.f, translation.z / 2.f, 0.f) * real;
183  }
184 
185  static const DualQuaternion identity()
186  {
187  return DualQuaternion(Quaternion(0.f, 0.f, 0.f, 1.f),
188  Quaternion(0.f, 0.f, 0.f, 0.f));
189  }
190 
191  template <typename V3>
192  static const DualQuaternion fromVector(const V3& vector)
193  {
194  return DualQuaternion(Quaternion(0.f, 0.f, 0.f, 1.f),
195  Quaternion(vector.x, vector.y, vector.z, 0.f));
196  }
197 
198  template <typename V3>
199  static const V3 toVector(const DualQuaternion& dq)
200  {
201  return V3(dq.dual.x, dq.dual.y, dq.dual.z);
202  }
203 
204  template <typename M4>
205  static const DualQuaternion fromMatrix(const M4& m)
206  {
207  const Quaternion rotation = Quaternion::fromMatrix(m);
208  const Quaternion translation = Quaternion(m(0,3) / 2.f,
209  m(1,3) / 2.f,
210  m(2,3) / 2.f,
211  0.f);
212  return DualQuaternion(rotation, translation*rotation);
213  }
214 
215  template <typename M4>
216  static const M4 toMatrix(const DualQuaternion& dq)
217  {
218  M4 m = Quaternion::toMatrix<M4>(dq.real);
219  const Quaternion translation = 2.f * dq.dual * conjugate(dq.real);
220  m(0,3) = translation.x;
221  m(1,3) = translation.y;
222  m(2,3) = translation.z;
223 
224  m(3,0) = 0.f;
225  m(3,1) = 0.f;
226  m(3,2) = 0.f;
227  m(3,3) = 1.f;
228  return m;
229  }
230 
232 };
233 static_assert(sizeof(DualQuaternion) == 8*4, "DualQuaternion is of unexpected size!");
234 static_assert(std::is_pod<DualQuaternion>::value == true, "DualQuaternion not POD!");
235 static_assert(std::is_trivial<DualQuaternion>::value == true, "DualQuaternion not trivial!");
236 static_assert(std::is_standard_layout<DualQuaternion>::value == true, "DualQuaternion not standard layout!");
243 
244 inline const DualQuaternion operator*(const DualQuaternion& a, const DualQuaternion& b)
245 {
249  return DualQuaternion(a.real*b.real,
250  a.real*b.dual + a.dual*b.real);
251 }
252 
254 {
256  return DualQuaternion(conjugate(dq.real),
257  Quaternion(dq.dual.x, dq.dual.y, dq.dual.z, -dq.dual.w));
258 }
259 
260 #endif
Quaternions are an extension of real numbers used to represent rotations in 3D.
Definition: DualQuaternion.hpp:22
Quaternion(const Q &q)
Definition: DualQuaternion.hpp:32
Quaternion()=default
static const DualQuaternion fromMatrix(const M4 &m)
Definition: DualQuaternion.hpp:205
static const Quaternion fromVector(const V3 &v)
Constructs a quaternion by embedding (identifying with) a 3D vector.
Definition: DualQuaternion.hpp:75
DualQuaternion(const V3 &translation, const Quaternion &rotation)
Definition: DualQuaternion.hpp:178
const Quaternion operator*(const Quaternion &a, const Quaternion &b)
Quaternion multiplication.
Definition: DualQuaternion.hpp:157
Quaternion(float x, float y, float z, float w)
Definition: DualQuaternion.hpp:26
static const DualQuaternion identity()
Definition: DualQuaternion.hpp:185
static const Quaternion identity()
Definition: DualQuaternion.hpp:59
const Quaternion operator+(const Quaternion &a, const Quaternion &b)
Returns a Quaternion that is the sum of quaternions a and b (component-wise sum). ...
Definition: DualQuaternion.hpp:148
Quaternion dual
Definition: DualQuaternion.hpp:231
static const DualQuaternion fromVector(const V3 &vector)
Definition: DualQuaternion.hpp:192
static const V3 toVector(const Quaternion &q)
Definition: DualQuaternion.hpp:68
static const Quaternion fromMatrix(const M3 &m)
Definition: DualQuaternion.hpp:109
DualQuaternion()=default
const DualQuaternion conjugateDual(const DualQuaternion &dq)
Definition: DualQuaternion.hpp:253
const Quaternion conjugate(const Quaternion &q)
Definition: DualQuaternion.hpp:165
Definition: DualQuaternion.hpp:170
Quaternion(F f)
Definition: DualQuaternion.hpp:42
DualQuaternion(const Quaternion &real, const Quaternion &dual)
Definition: DualQuaternion.hpp:174
nv::matrix4f translation(const nv::vec3f &t)
Definition: AngryDudeApp.cpp:191
float y
Definition: DualQuaternion.hpp:141
float x
Definition: DualQuaternion.hpp:141
static const M3 toMatrix(const Quaternion &q)
Definition: DualQuaternion.hpp:84
static const V3 toVector(const DualQuaternion &dq)
Definition: DualQuaternion.hpp:199
static const M4 toMatrix(const DualQuaternion &dq)
Definition: DualQuaternion.hpp:216
Quaternion real
Definition: DualQuaternion.hpp:231
Quaternion(const V3 &unitAxis, float thetaRadians)
Constructs a unit quaternion from the specified unit 3D vector and rotation angle.
Definition: DualQuaternion.hpp:46
float w
Scalar part of the quaternion.
Definition: DualQuaternion.hpp:144
float z
Vector part of the quaternion.
Definition: DualQuaternion.hpp:141