Euphoria
quat.cc
Go to the documentation of this file.
1 #include "base/quat.h"
2 
3 
4 namespace eu
5 {
7  {
8  return &w;
9  }
10 
11  [[nodiscard]] const float* quatf::get_data_ptr() const
12  {
13  return &w;
14  }
15 
17  {
18  return {x, y, z};
19  }
20 
21 
22  [[nodiscard]] quatf
24  {
25  const float sin_a = sin(aa.angle / 2);
26  const float cos_a = cos(aa.angle / 2);
27  quatf r(cos_a, aa.axis * sin_a);
28  r.normalize();
29  return r;
30  }
31 
32 
33  [[nodiscard]] quatf
34  quatf::from_ypr(const Angle& yaw, const Angle& pitch, const Angle& roll)
35  {
36  // Abbreviations for the various angular functions
37  const auto cy = cos(yaw * 0.5);
38  const auto sy = sin(yaw * 0.5);
39  const auto cp = cos(pitch * 0.5);
40  const auto sp = sin(pitch * 0.5);
41  const auto cr = cos(roll * 0.5);
42  const auto sr = sin(roll * 0.5);
43 
44  return
45  {
46  cr * cp * cy + sr * sp * sy,
47  {
48  sr * cp * cy - cr * sp * sy,
49  cr * sp * cy + sr * cp * sy,
50  cr * cp * sy - sr * sp * cy
51  }
52  };
53  }
54 
55 
56  [[nodiscard]] quatf
57  quatf::from_to(const quatf& from, const quatf& to)
58  {
59  // https://stackoverflow.com/a/22167097
60  return to * from.get_inverse();
61  }
62 
63 
64  [[nodiscard]] quatf
66  {
67  const auto axis = get_random_unit3(random);
68  const auto angle = get_random_angle(random);
69 
71  }
72 
73 
74  [[nodiscard]] mat4f
76  {
78  }
79 
80 
81  [[nodiscard]] AxisAngle
83  {
84  const float cos_a = w;
85  const auto angle = acos(cos_a) * 2;
86  const auto sin_a = get_default_if_close_to_zero<float>(
87  sqrt(1.0f - cos_a * cos_a), 1, 0.0005f);
88  // todo(Gustav): do we need to normalize here?
90  (get_vec_part() / sin_a).get_normalized(), angle);
91  }
92 
93 
94  // static Q FromAngles(float x, float y, float z);
95 
96 
97  [[nodiscard]] quatf
98  quatf::look_at(const vec3f& from, const vec3f& to, const unit3f& up)
99  {
100  return look_in_direction(vec3f::from_to(from, to).get_normalized(), up);
101  }
102 
103 
104  quatf
105  quatf::get_rotated(const quatf& q) const
106  {
107  return q * *this;
108  }
109 
110 
111  quatf
113  {
114  return {w, -get_vec_part()};
115  }
116 
117 
118  quatf
120  {
121  // todo(Gustav): assert here
122  // get_length_squared() == 1
123  return get_conjugate();
124  }
125 
126 
127  // the negated represents the same rotation
128  quatf
130  {
131  return {-w, -get_vec_part()};
132  }
133 
134 
135  quatf
137  {
138  const float l2 = get_length_squared();
139  if(is_equal(l2, 0.0f)) { return q_identity; }
140  else if(is_equal(l2, 1.0f)) { return get_conjugate(); }
141  else { return {w / sqrt(l2), -get_vec_part()}; }
142  }
143 
144 
145  float
147  {
148  return sqrt(get_length_squared());
149  }
150 
151 
152  float
154  {
155  return x * x + y * y + z * z + w * w;
156  }
157 
158 
159  void
161  {
162  const float l = get_length();
163  if(is_zero(l))
164  {
165  *this = q_identity;
166  }
167  else
168  {
169  x /= l;
170  y /= l;
171  z /= l;
172  w /= l;
173  }
174  }
175 
176 
177  quatf
179  {
180  quatf r = *this;
181  r.normalize();
182  return r;
183  }
184 
185 
192 
193 
194  // In*Z + Right*X + Up*Y
195  vec3f
197  {
198  return get_in() * v.z + get_right() * v.x + get_up() * v.y;
199  }
200 
201 
202  unit3f
204  {
205  // http://gamedev.stackexchange.com/questions/28395/rotating-vector3-by-a-quaternion
206  const quatf pure = {0, v};
207  const quatf a = *this * pure;
208  const quatf ret = a * get_conjugate();
209  return ret.get_vec_part().get_normalized();
210  }
211 
212 
213  quatf
214  lerp_quatf(const quatf& f, const float scale, const quatf& t)
215  {
216  return f * (1 - scale) + t * scale;
217  }
218 
219 
220  quatf
221  slerp_fast(const quatf& qa, const float t, const quatf& qb)
222  {
223  // from:
224  // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
225  // Calculate angle between them.
226  const float cos_half_theta = qa.w * qb.w + qa.x * qb.x + qa.y * qb.y + qa.z * qb.z;
227  // if qa=qb or qa=-qb then theta = 0 and we can return qa
228  if(abs(cos_half_theta) >= 1.0f)
229  {
230  return qa;
231  }
232  // Calculate temporary values.
233  const auto half_theta = acos(cos_half_theta);
234  const auto sin_half_theta = sqrt(1.0f - cos_half_theta * cos_half_theta);
235  if(abs(sin_half_theta) < 0.001f)
236  {
237  // if theta = 180 degrees then result is not fully defined
238  // we could rotate around any axis normal to qa or qb
239  const quatf qt = qa + qb;
240  return quatf
241  {
242  qt.w * 0.5f,
243  vec3f
244  {
245  qt.x * 0.5f,
246  qt.y * 0.5f,
247  qt.z * 0.5f
248  }
249  };
250  }
251  const float ratio_a = sin((1 - t) * half_theta) / sin_half_theta;
252  const float ratio_b = sin(t * half_theta) / sin_half_theta;
253  return qa * ratio_a + qb * ratio_b;
254  }
255 
256 
257  quatf
258  slerp_shortway(const quatf& from, const float scale, const quatf& to)
259  {
260  if(dot(from, to) < 0)
261  {
262  return slerp_fast(from.get_negated(), scale, to);
263  }
264  else
265  {
266  return slerp_fast(from, scale, to);
267  }
268  }
269 
270 
271  void
273  {
274  x += rhs.x;
275  y += rhs.y;
276  z += rhs.z;
277  w += rhs.w;
278  }
279 
280 
281  void
283  {
284  x -= rhs.x;
285  y -= rhs.y;
286  z -= rhs.z;
287  w -= rhs.w;
288  }
289 
290 
291  void
292  quatf::operator*=(float rhs)
293  {
294  x *= rhs;
295  y *= rhs;
296  z *= rhs;
297  w *= rhs;
298  }
299 
300 
301  void
303  {
304 #define VAR(a, b) const float a##1##b##2 = a * rhs.b
305  VAR(w, w);
306  VAR(w, x);
307  VAR(w, y);
308  VAR(w, z);
309 
310  VAR(x, w);
311  VAR(x, x);
312  VAR(x, y);
313  VAR(x, z);
314 
315  VAR(y, w);
316  VAR(y, x);
317  VAR(y, y);
318  VAR(y, z);
319 
320  VAR(z, w);
321  VAR(z, x);
322  VAR(z, y);
323  VAR(z, z);
324 #undef VAR
325 
326  w = w1w2 - x1x2 - y1y2 - z1z2;
327  x = w1x2 + x1w2 + y1z2 - z1y2;
328  y = w1y2 + y1w2 + z1x2 - x1z2;
329  z = w1z2 + z1w2 + x1y2 - y1x2;
330  }
331 
333  {
334  const vec3f in = common::in;
335  float dot_value = in.dot(dir);
336 
337  if (abs(dot_value - (-1.0f)) < 0.000001f)
338  {
339  // todo(Gustav): replace with a constant in general but this line specifically
340  return {3.1415926535897932f, up};
341  }
342  if (abs(dot_value - (1.0f)) < 0.000001f)
343  {
344  return q_identity;
345  }
346 
347  const auto rot_angle = acos(dot_value);
348  const auto rot_axis = in.cross(dir).get_normalized();
350  (
351  AxisAngle::from_right_hand_around(rot_axis, rot_angle)
352  );
353  }
354 
355 
356  std::string to_string(const quatf& v)
357  {
358  return fmt::format("({} ({}, {}, {}))", v.w, v.x, v.y, v.z);
359  }
360 
361 
362  float
363  dot(const quatf& lhs, const quatf& rhs)
364  {
365  return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z + lhs.w * rhs.w;
366  }
367 
368 
369  quatf operator*(const quatf& lhs, const quatf& rhs)
370  {
371  quatf r = lhs;
372  r *= rhs;
373  return r;
374  }
375 
376 
377  quatf operator*(float scale, const quatf& q)
378  {
379  quatf r = q;
380  r *= scale;
381  return r;
382  }
383 
384 
385  quatf operator*(const quatf& q, float scale)
386  {
387  quatf r = q;
388  r *= scale;
389  return r;
390  }
391 
392 
393  quatf
394  operator+(const quatf& lhs, const quatf& rhs)
395  {
396  quatf r = rhs;
397  r += lhs;
398  return r;
399  }
400 
401 
402  quatf
403  operator-(const quatf& lhs, const quatf& rhs)
404  {
405  quatf r = rhs;
406  r -= lhs;
407  return r;
408  }
409 }
410 
constexpr unit3f in
Definition: vec3.h:135
constexpr unit3f x_axis
Definition: vec3.h:128
constexpr unit3f y_axis
Definition: vec3.h:129
constexpr unit3f z_axis
Definition: vec3.h:130
Definition: assert.h:90
float sqrt(float r)
Definition: numeric.cc:101
Angle operator+(const Angle &lhs, const Angle &rhs)
Definition: angle.cc:123
constexpr quatf q_identity
Definition: quat.h:71
Angle acos(float v)
Definition: angle.cc:91
Angle operator-(const Angle &lhs, const Angle &rhs)
Definition: angle.cc:132
quatf slerp_fast(const quatf &qa, const float t, const quatf &qb)
Definition: quat.cc:221
bool is_zero(int r)
Definition: numeric.cc:20
constexpr float abs(float r)
Definition: numeric.h:8
quatf lerp_quatf(const quatf &f, const float scale, const quatf &t)
Definition: quat.cc:214
std::string to_string(const Aabb &a)
Definition: aabb.cc:110
bool is_equal(int lhs, int rhs)
Definition: numeric.cc:13
unit3f get_random_unit3(Random *random)
Definition: polarcoord.cc:42
float cos(const Angle &ang)
Definition: angle.cc:68
quatf slerp_shortway(const quatf &from, const float scale, const quatf &to)
Definition: quat.cc:258
Angle get_random_angle(::eu::Random *random)
Definition: angle.cc:12
float sin(const Angle &ang)
Definition: angle.cc:61
Angle operator*(const Angle &lhs, float rhs)
Definition: angle.cc:149
float dot(const quatf &lhs, const quatf &rhs)
Definition: quat.cc:363
#define VAR(a, b)
unit3f axis
a unit-vector
Definition: axisangle.h:13
Angle angle
rotation according to right-hand rule
Definition: axisangle.h:16
static AxisAngle from_right_hand_around(const unit3f &axis, const Angle &angle)
Definition: axisangle.cc:14
WEL512 Random Number Generator.
Definition: random.h:21
Definition: mat4.h:14
static mat4f from_axis_angle(const AxisAngle &aa)
Definition: mat4.cc:146
Definition: quat.h:15
static quatf look_in_direction(const unit3f &dir, const unit3f &up)
Definition: quat.cc:332
mat4f to_mat4() const
Definition: quat.cc:75
float y
Definition: quat.h:18
AxisAngle to_axis_angle() const
Definition: quat.cc:82
quatf get_conjugate() const
Definition: quat.cc:112
float z
Definition: quat.h:19
void normalize()
Definition: quat.cc:160
float get_length_squared() const
Definition: quat.cc:153
static quatf from_random(Random *random)
Definition: quat.cc:65
quatf get_identity() const
Definition: quat.cc:136
float x
Definition: quat.h:17
static quatf from_to(const quatf &from, const quatf &to)
Definition: quat.cc:57
unit3f get_left() const
Definition: quat.cc:189
static quatf from_axis_angle(const AxisAngle &aa)
Definition: quat.cc:23
unit3f get_in() const
Definition: quat.cc:186
void operator-=(const quatf &rhs)
Definition: quat.cc:282
vec3f get_vec_part() const
Definition: quat.cc:16
unit3f rotate_around_origo(const unit3f &v) const
Definition: quat.cc:203
unit3f get_out() const
Definition: quat.cc:187
quatf get_normalized() const
Definition: quat.cc:178
float get_length() const
Definition: quat.cc:146
float * get_data_ptr()
Definition: quat.cc:6
unit3f get_up() const
Definition: quat.cc:190
float w
Definition: quat.h:16
quatf get_negated() const
Definition: quat.cc:129
void operator*=(float rhs)
Definition: quat.cc:292
unit3f get_right() const
Definition: quat.cc:188
static quatf from_ypr(const Angle &yaw, const Angle &pitch, const Angle &roll)
Definition: quat.cc:34
vec3f create_from_right_up_in(const vec3f &v) const
returns In*Z + Right*X + Up*Y
Definition: quat.cc:196
quatf get_rotated(const quatf &q) const
Definition: quat.cc:105
unit3f get_down() const
Definition: quat.cc:191
void operator+=(const quatf &rhs)
Definition: quat.cc:272
static quatf look_at(const vec3f &from, const vec3f &to, const unit3f &up)
Definition: quat.cc:98
quatf get_inverse() const
Definition: quat.cc:119
Definition: vec3.h:48
unit3f get_normalized() const
Definition: vec3.cc:174
vec3f cross(const vec3f &u) const
Definition: vec3.cc:283
static vec3f from_to(const vec3f &from, const vec3f &to)
Definition: vec3.cc:127
float dot(const vec3f &rhs) const
Definition: vec3.cc:276