Blender  V3.3
math_rotation.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
8 #include "BLI_math.h"
9 
10 #include "BLI_strict_flags.h"
11 
12 /******************************** Quaternions ********************************/
13 
14 /* used to test is a quat is not normalized (only used for debug prints) */
15 #ifdef DEBUG
16 # define QUAT_EPSILON 0.0001
17 #endif
18 
19 void unit_axis_angle(float axis[3], float *angle)
20 {
21  axis[0] = 0.0f;
22  axis[1] = 1.0f;
23  axis[2] = 0.0f;
24  *angle = 0.0f;
25 }
26 
27 void unit_qt(float q[4])
28 {
29  q[0] = 1.0f;
30  q[1] = q[2] = q[3] = 0.0f;
31 }
32 
33 void copy_qt_qt(float q[4], const float a[4])
34 {
35  q[0] = a[0];
36  q[1] = a[1];
37  q[2] = a[2];
38  q[3] = a[3];
39 }
40 
41 bool is_zero_qt(const float q[4])
42 {
43  return (q[0] == 0 && q[1] == 0 && q[2] == 0 && q[3] == 0);
44 }
45 
46 void mul_qt_qtqt(float q[4], const float a[4], const float b[4])
47 {
48  float t0, t1, t2;
49 
50  t0 = a[0] * b[0] - a[1] * b[1] - a[2] * b[2] - a[3] * b[3];
51  t1 = a[0] * b[1] + a[1] * b[0] + a[2] * b[3] - a[3] * b[2];
52  t2 = a[0] * b[2] + a[2] * b[0] + a[3] * b[1] - a[1] * b[3];
53  q[3] = a[0] * b[3] + a[3] * b[0] + a[1] * b[2] - a[2] * b[1];
54  q[0] = t0;
55  q[1] = t1;
56  q[2] = t2;
57 }
58 
59 void mul_qt_v3(const float q[4], float r[3])
60 {
61  float t0, t1, t2;
62 
63  t0 = -q[1] * r[0] - q[2] * r[1] - q[3] * r[2];
64  t1 = q[0] * r[0] + q[2] * r[2] - q[3] * r[1];
65  t2 = q[0] * r[1] + q[3] * r[0] - q[1] * r[2];
66  r[2] = q[0] * r[2] + q[1] * r[1] - q[2] * r[0];
67  r[0] = t1;
68  r[1] = t2;
69 
70  t1 = t0 * -q[1] + r[0] * q[0] - r[1] * q[3] + r[2] * q[2];
71  t2 = t0 * -q[2] + r[1] * q[0] - r[2] * q[1] + r[0] * q[3];
72  r[2] = t0 * -q[3] + r[2] * q[0] - r[0] * q[2] + r[1] * q[1];
73  r[0] = t1;
74  r[1] = t2;
75 }
76 
77 void conjugate_qt_qt(float q1[4], const float q2[4])
78 {
79  q1[0] = q2[0];
80  q1[1] = -q2[1];
81  q1[2] = -q2[2];
82  q1[3] = -q2[3];
83 }
84 
85 void conjugate_qt(float q[4])
86 {
87  q[1] = -q[1];
88  q[2] = -q[2];
89  q[3] = -q[3];
90 }
91 
92 float dot_qtqt(const float a[4], const float b[4])
93 {
94  return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
95 }
96 
97 void invert_qt(float q[4])
98 {
99  const float f = dot_qtqt(q, q);
100 
101  if (f == 0.0f) {
102  return;
103  }
104 
105  conjugate_qt(q);
106  mul_qt_fl(q, 1.0f / f);
107 }
108 
109 void invert_qt_qt(float q1[4], const float q2[4])
110 {
111  copy_qt_qt(q1, q2);
112  invert_qt(q1);
113 }
114 
115 void invert_qt_normalized(float q[4])
116 {
118  conjugate_qt(q);
119 }
120 
121 void invert_qt_qt_normalized(float q1[4], const float q2[4])
122 {
123  copy_qt_qt(q1, q2);
125 }
126 
127 void mul_qt_fl(float q[4], const float f)
128 {
129  q[0] *= f;
130  q[1] *= f;
131  q[2] *= f;
132  q[3] *= f;
133 }
134 
135 void sub_qt_qtqt(float q[4], const float a[4], const float b[4])
136 {
137  float n_b[4];
138 
139  n_b[0] = -b[0];
140  n_b[1] = b[1];
141  n_b[2] = b[2];
142  n_b[3] = b[3];
143 
144  mul_qt_qtqt(q, a, n_b);
145 }
146 
147 void pow_qt_fl_normalized(float q[4], const float fac)
148 {
150  const float angle = fac * saacos(q[0]); /* quat[0] = cos(0.5 * angle),
151  * but now the 0.5 and 2.0 rule out */
152  const float co = cosf(angle);
153  const float si = sinf(angle);
154  q[0] = co;
155  normalize_v3_length(q + 1, si);
156 }
157 
158 void quat_to_compatible_quat(float q[4], const float a[4], const float old[4])
159 {
160  const float eps = 1e-4f;
162  float old_unit[4];
163  /* Skips `!finite_v4(old)` case too. */
164  if (normalize_qt_qt(old_unit, old) > eps) {
165  float q_negate[4];
166  float delta[4];
167  rotation_between_quats_to_quat(delta, old_unit, a);
168  mul_qt_qtqt(q, old, delta);
169  negate_v4_v4(q_negate, q);
170  if (len_squared_v4v4(q_negate, old) < len_squared_v4v4(q, old)) {
171  copy_qt_qt(q, q_negate);
172  }
173  }
174  else {
175  copy_qt_qt(q, a);
176  }
177 }
178 
179 /* skip error check, currently only needed by mat3_to_quat_is_ok */
180 static void quat_to_mat3_no_error(float m[3][3], const float q[4])
181 {
182  double q0, q1, q2, q3, qda, qdb, qdc, qaa, qab, qac, qbb, qbc, qcc;
183 
184  q0 = M_SQRT2 * (double)q[0];
185  q1 = M_SQRT2 * (double)q[1];
186  q2 = M_SQRT2 * (double)q[2];
187  q3 = M_SQRT2 * (double)q[3];
188 
189  qda = q0 * q1;
190  qdb = q0 * q2;
191  qdc = q0 * q3;
192  qaa = q1 * q1;
193  qab = q1 * q2;
194  qac = q1 * q3;
195  qbb = q2 * q2;
196  qbc = q2 * q3;
197  qcc = q3 * q3;
198 
199  m[0][0] = (float)(1.0 - qbb - qcc);
200  m[0][1] = (float)(qdc + qab);
201  m[0][2] = (float)(-qdb + qac);
202 
203  m[1][0] = (float)(-qdc + qab);
204  m[1][1] = (float)(1.0 - qaa - qcc);
205  m[1][2] = (float)(qda + qbc);
206 
207  m[2][0] = (float)(qdb + qac);
208  m[2][1] = (float)(-qda + qbc);
209  m[2][2] = (float)(1.0 - qaa - qbb);
210 }
211 
212 void quat_to_mat3(float m[3][3], const float q[4])
213 {
214 #ifdef DEBUG
215  float f;
216  if (!((f = dot_qtqt(q, q)) == 0.0f || (fabsf(f - 1.0f) < (float)QUAT_EPSILON))) {
217  fprintf(stderr,
218  "Warning! quat_to_mat3() called with non-normalized: size %.8f *** report a bug ***\n",
219  f);
220  }
221 #endif
222 
223  quat_to_mat3_no_error(m, q);
224 }
225 
226 void quat_to_mat4(float m[4][4], const float q[4])
227 {
228  double q0, q1, q2, q3, qda, qdb, qdc, qaa, qab, qac, qbb, qbc, qcc;
229 
230 #ifdef DEBUG
231  if (!((q0 = dot_qtqt(q, q)) == 0.0 || (fabs(q0 - 1.0) < QUAT_EPSILON))) {
232  fprintf(stderr,
233  "Warning! quat_to_mat4() called with non-normalized: size %.8f *** report a bug ***\n",
234  (float)q0);
235  }
236 #endif
237 
238  q0 = M_SQRT2 * (double)q[0];
239  q1 = M_SQRT2 * (double)q[1];
240  q2 = M_SQRT2 * (double)q[2];
241  q3 = M_SQRT2 * (double)q[3];
242 
243  qda = q0 * q1;
244  qdb = q0 * q2;
245  qdc = q0 * q3;
246  qaa = q1 * q1;
247  qab = q1 * q2;
248  qac = q1 * q3;
249  qbb = q2 * q2;
250  qbc = q2 * q3;
251  qcc = q3 * q3;
252 
253  m[0][0] = (float)(1.0 - qbb - qcc);
254  m[0][1] = (float)(qdc + qab);
255  m[0][2] = (float)(-qdb + qac);
256  m[0][3] = 0.0f;
257 
258  m[1][0] = (float)(-qdc + qab);
259  m[1][1] = (float)(1.0 - qaa - qcc);
260  m[1][2] = (float)(qda + qbc);
261  m[1][3] = 0.0f;
262 
263  m[2][0] = (float)(qdb + qac);
264  m[2][1] = (float)(-qda + qbc);
265  m[2][2] = (float)(1.0 - qaa - qbb);
266  m[2][3] = 0.0f;
267 
268  m[3][0] = m[3][1] = m[3][2] = 0.0f;
269  m[3][3] = 1.0f;
270 }
271 
272 void mat3_normalized_to_quat(float q[4], const float mat[3][3])
273 {
274  BLI_ASSERT_UNIT_M3(mat);
275 
276  /* Check the trace of the matrix - bad precision if close to -1. */
277  const float trace = mat[0][0] + mat[1][1] + mat[2][2];
278 
279  if (trace > 0) {
280  float s = 2.0f * sqrtf(1.0f + trace);
281 
282  q[0] = 0.25f * s;
283 
284  s = 1.0f / s;
285 
286  q[1] = (mat[1][2] - mat[2][1]) * s;
287  q[2] = (mat[2][0] - mat[0][2]) * s;
288  q[3] = (mat[0][1] - mat[1][0]) * s;
289  }
290  else {
291  /* Find the biggest diagonal element to choose the best formula.
292  * Here trace should also be always >= 0, avoiding bad precision. */
293  if (mat[0][0] > mat[1][1] && mat[0][0] > mat[2][2]) {
294  float s = 2.0f * sqrtf(1.0f + mat[0][0] - mat[1][1] - mat[2][2]);
295 
296  q[1] = 0.25f * s;
297 
298  s = 1.0f / s;
299 
300  q[0] = (mat[1][2] - mat[2][1]) * s;
301  q[2] = (mat[1][0] + mat[0][1]) * s;
302  q[3] = (mat[2][0] + mat[0][2]) * s;
303  }
304  else if (mat[1][1] > mat[2][2]) {
305  float s = 2.0f * sqrtf(1.0f + mat[1][1] - mat[0][0] - mat[2][2]);
306 
307  q[2] = 0.25f * s;
308 
309  s = 1.0f / s;
310 
311  q[0] = (mat[2][0] - mat[0][2]) * s;
312  q[1] = (mat[1][0] + mat[0][1]) * s;
313  q[3] = (mat[2][1] + mat[1][2]) * s;
314  }
315  else {
316  float s = 2.0f * sqrtf(1.0f + mat[2][2] - mat[0][0] - mat[1][1]);
317 
318  q[3] = 0.25f * s;
319 
320  s = 1.0f / s;
321 
322  q[0] = (mat[0][1] - mat[1][0]) * s;
323  q[1] = (mat[2][0] + mat[0][2]) * s;
324  q[2] = (mat[2][1] + mat[1][2]) * s;
325  }
326 
327  /* Make sure W is non-negative for a canonical result. */
328  if (q[0] < 0) {
329  negate_v4(q);
330  }
331  }
332 
333  normalize_qt(q);
334 }
335 void mat3_to_quat(float q[4], const float m[3][3])
336 {
337  float unit_mat[3][3];
338 
339  /* work on a copy */
340  /* this is needed AND a 'normalize_qt' in the end */
341  normalize_m3_m3(unit_mat, m);
342  mat3_normalized_to_quat(q, unit_mat);
343 }
344 
345 void mat4_normalized_to_quat(float q[4], const float m[4][4])
346 {
347  float mat3[3][3];
348 
349  copy_m3_m4(mat3, m);
350  mat3_normalized_to_quat(q, mat3);
351 }
352 
353 void mat4_to_quat(float q[4], const float m[4][4])
354 {
355  float mat3[3][3];
356 
357  copy_m3_m4(mat3, m);
358  mat3_to_quat(q, mat3);
359 }
360 
361 void mat3_to_quat_is_ok(float q[4], const float wmat[3][3])
362 {
363  float mat[3][3], matr[3][3], matn[3][3], q1[4], q2[4], angle, si, co, nor[3];
364 
365  /* work on a copy */
366  copy_m3_m3(mat, wmat);
367  normalize_m3(mat);
368 
369  /* rotate z-axis of matrix to z-axis */
370 
371  nor[0] = mat[2][1]; /* cross product with (0,0,1) */
372  nor[1] = -mat[2][0];
373  nor[2] = 0.0;
374  normalize_v3(nor);
375 
376  co = mat[2][2];
377  angle = 0.5f * saacos(co);
378 
379  co = cosf(angle);
380  si = sinf(angle);
381  q1[0] = co;
382  q1[1] = -nor[0] * si; /* negative here, but why? */
383  q1[2] = -nor[1] * si;
384  q1[3] = -nor[2] * si;
385 
386  /* rotate back x-axis from mat, using inverse q1 */
387  quat_to_mat3_no_error(matr, q1);
388  invert_m3_m3(matn, matr);
389  mul_m3_v3(matn, mat[0]);
390 
391  /* and align x-axes */
392  angle = 0.5f * atan2f(mat[0][1], mat[0][0]);
393 
394  co = cosf(angle);
395  si = sinf(angle);
396  q2[0] = co;
397  q2[1] = 0.0f;
398  q2[2] = 0.0f;
399  q2[3] = si;
400 
401  mul_qt_qtqt(q, q1, q2);
402 }
403 
404 float normalize_qt(float q[4])
405 {
406  const float len = sqrtf(dot_qtqt(q, q));
407 
408  if (len != 0.0f) {
409  mul_qt_fl(q, 1.0f / len);
410  }
411  else {
412  q[1] = 1.0f;
413  q[0] = q[2] = q[3] = 0.0f;
414  }
415 
416  return len;
417 }
418 
419 float normalize_qt_qt(float r[4], const float q[4])
420 {
421  copy_qt_qt(r, q);
422  return normalize_qt(r);
423 }
424 
425 void rotation_between_vecs_to_mat3(float m[3][3], const float v1[3], const float v2[3])
426 {
427  float axis[3];
428  /* avoid calculating the angle */
429  float angle_sin;
430  float angle_cos;
431 
434 
435  cross_v3_v3v3(axis, v1, v2);
436 
437  angle_sin = normalize_v3(axis);
438  angle_cos = dot_v3v3(v1, v2);
439 
440  if (angle_sin > FLT_EPSILON) {
441  axis_calc:
442  BLI_ASSERT_UNIT_V3(axis);
443  axis_angle_normalized_to_mat3_ex(m, axis, angle_sin, angle_cos);
445  }
446  else {
447  if (angle_cos > 0.0f) {
448  /* Same vectors, zero rotation... */
449  unit_m3(m);
450  }
451  else {
452  /* Colinear but opposed vectors, 180 rotation... */
453  ortho_v3_v3(axis, v1);
454  normalize_v3(axis);
455  angle_sin = 0.0f; /* sin(M_PI) */
456  angle_cos = -1.0f; /* cos(M_PI) */
457  goto axis_calc;
458  }
459  }
460 }
461 
462 void rotation_between_vecs_to_quat(float q[4], const float v1[3], const float v2[3])
463 {
464  float axis[3];
465 
466  cross_v3_v3v3(axis, v1, v2);
467 
468  if (normalize_v3(axis) > FLT_EPSILON) {
469  float angle;
470 
472 
474  }
475  else {
476  /* degenerate case */
477 
478  if (dot_v3v3(v1, v2) > 0.0f) {
479  /* Same vectors, zero rotation... */
480  unit_qt(q);
481  }
482  else {
483  /* Colinear but opposed vectors, 180 rotation... */
484  ortho_v3_v3(axis, v1);
485  axis_angle_to_quat(q, axis, (float)M_PI);
486  }
487  }
488 }
489 
490 void rotation_between_quats_to_quat(float q[4], const float q1[4], const float q2[4])
491 {
492  float tquat[4];
493 
494  conjugate_qt_qt(tquat, q1);
495 
496  mul_qt_fl(tquat, 1.0f / dot_qtqt(tquat, tquat));
497 
498  mul_qt_qtqt(q, tquat, q2);
499 }
500 
501 float quat_split_swing_and_twist(const float q_in[4], int axis, float r_swing[4], float r_twist[4])
502 {
503  BLI_assert(axis >= 0 && axis <= 2);
504 
505  /* The calculation requires a canonical quaternion. */
506  float q[4];
507 
508  if (q_in[0] < 0) {
509  negate_v4_v4(q, q_in);
510  }
511  else {
512  copy_v4_v4(q, q_in);
513  }
514 
515  /* Half-twist angle can be computed directly. */
516  float t = atan2f(q[axis + 1], q[0]);
517 
518  if (r_swing || r_twist) {
519  float sin_t = sinf(t), cos_t = cosf(t);
520 
521  /* Compute swing by multiplying the original quaternion by inverted twist. */
522  if (r_swing) {
523  float twist_inv[4];
524 
525  twist_inv[0] = cos_t;
526  zero_v3(twist_inv + 1);
527  twist_inv[axis + 1] = -sin_t;
528 
529  mul_qt_qtqt(r_swing, q, twist_inv);
530 
531  BLI_assert(fabsf(r_swing[axis + 1]) < BLI_ASSERT_UNIT_EPSILON);
532  }
533 
534  /* Output twist last just in case q overlaps r_twist. */
535  if (r_twist) {
536  r_twist[0] = cos_t;
537  zero_v3(r_twist + 1);
538  r_twist[axis + 1] = sin_t;
539  }
540  }
541 
542  return 2.0f * t;
543 }
544 
545 /* -------------------------------------------------------------------- */
553 float angle_normalized_qt(const float q[4])
554 {
556  return 2.0f * saacos(q[0]);
557 }
558 
559 float angle_qt(const float q[4])
560 {
561  float tquat[4];
562 
563  normalize_qt_qt(tquat, q);
564 
565  return angle_normalized_qt(tquat);
566 }
567 
568 float angle_normalized_qtqt(const float q1[4], const float q2[4])
569 {
570  float qdelta[4];
571 
574 
575  rotation_between_quats_to_quat(qdelta, q1, q2);
576 
577  return angle_normalized_qt(qdelta);
578 }
579 
580 float angle_qtqt(const float q1[4], const float q2[4])
581 {
582  float quat1[4], quat2[4];
583 
584  normalize_qt_qt(quat1, q1);
585  normalize_qt_qt(quat2, q2);
586 
587  return angle_normalized_qtqt(quat1, quat2);
588 }
589 
592 /* -------------------------------------------------------------------- */
602 float angle_signed_normalized_qt(const float q[4])
603 {
605  if (q[0] >= 0.0f) {
606  return 2.0f * saacos(q[0]);
607  }
608 
609  return -2.0f * saacos(-q[0]);
610 }
611 
612 float angle_signed_normalized_qtqt(const float q1[4], const float q2[4])
613 {
614  if (dot_qtqt(q1, q2) >= 0.0f) {
615  return angle_normalized_qtqt(q1, q2);
616  }
617 
618  float q2_copy[4];
619  negate_v4_v4(q2_copy, q2);
620  return -angle_normalized_qtqt(q1, q2_copy);
621 }
622 
623 float angle_signed_qt(const float q[4])
624 {
625  float tquat[4];
626 
627  normalize_qt_qt(tquat, q);
628 
629  return angle_signed_normalized_qt(tquat);
630 }
631 
632 float angle_signed_qtqt(const float q1[4], const float q2[4])
633 {
634  if (dot_qtqt(q1, q2) >= 0.0f) {
635  return angle_qtqt(q1, q2);
636  }
637 
638  float q2_copy[4];
639  negate_v4_v4(q2_copy, q2);
640  return -angle_qtqt(q1, q2_copy);
641 }
642 
645 void vec_to_quat(float q[4], const float vec[3], short axis, const short upflag)
646 {
647  const float eps = 1e-4f;
648  float nor[3], tvec[3];
649  float angle, si, co, len;
650 
651  BLI_assert(axis >= 0 && axis <= 5);
652  BLI_assert(upflag >= 0 && upflag <= 2);
653 
654  /* first set the quat to unit */
655  unit_qt(q);
656 
657  len = len_v3(vec);
658 
659  if (UNLIKELY(len == 0.0f)) {
660  return;
661  }
662 
663  /* rotate to axis */
664  if (axis > 2) {
665  copy_v3_v3(tvec, vec);
666  axis = (short)(axis - 3);
667  }
668  else {
669  negate_v3_v3(tvec, vec);
670  }
671 
672  /* nasty! I need a good routine for this...
673  * problem is a rotation of an Y axis to the negative Y-axis for example.
674  */
675 
676  if (axis == 0) { /* x-axis */
677  nor[0] = 0.0;
678  nor[1] = -tvec[2];
679  nor[2] = tvec[1];
680 
681  if (fabsf(tvec[1]) + fabsf(tvec[2]) < eps) {
682  nor[1] = 1.0f;
683  }
684 
685  co = tvec[0];
686  }
687  else if (axis == 1) { /* y-axis */
688  nor[0] = tvec[2];
689  nor[1] = 0.0;
690  nor[2] = -tvec[0];
691 
692  if (fabsf(tvec[0]) + fabsf(tvec[2]) < eps) {
693  nor[2] = 1.0f;
694  }
695 
696  co = tvec[1];
697  }
698  else { /* z-axis */
699  nor[0] = -tvec[1];
700  nor[1] = tvec[0];
701  nor[2] = 0.0;
702 
703  if (fabsf(tvec[0]) + fabsf(tvec[1]) < eps) {
704  nor[0] = 1.0f;
705  }
706 
707  co = tvec[2];
708  }
709  co /= len;
710 
711  normalize_v3(nor);
712 
714 
715  if (axis != upflag) {
716  float mat[3][3];
717  float q2[4];
718  const float *fp = mat[2];
719  quat_to_mat3(mat, q);
720 
721  if (axis == 0) {
722  if (upflag == 1) {
723  angle = 0.5f * atan2f(fp[2], fp[1]);
724  }
725  else {
726  angle = -0.5f * atan2f(fp[1], fp[2]);
727  }
728  }
729  else if (axis == 1) {
730  if (upflag == 0) {
731  angle = -0.5f * atan2f(fp[2], fp[0]);
732  }
733  else {
734  angle = 0.5f * atan2f(fp[0], fp[2]);
735  }
736  }
737  else {
738  if (upflag == 0) {
739  angle = 0.5f * atan2f(-fp[1], -fp[0]);
740  }
741  else {
742  angle = -0.5f * atan2f(-fp[0], -fp[1]);
743  }
744  }
745 
746  co = cosf(angle);
747  si = sinf(angle) / len;
748  q2[0] = co;
749  q2[1] = tvec[0] * si;
750  q2[2] = tvec[1] * si;
751  q2[3] = tvec[2] * si;
752 
753  mul_qt_qtqt(q, q2, q);
754  }
755 }
756 
757 #if 0
758 
759 /* A & M Watt, Advanced animation and rendering techniques, 1992 ACM press */
760 void QuatInterpolW(float *result, float quat1[4], float quat2[4], float t)
761 {
762  float omega, cosom, sinom, sc1, sc2;
763 
764  cosom = quat1[0] * quat2[0] + quat1[1] * quat2[1] + quat1[2] * quat2[2] + quat1[3] * quat2[3];
765 
766  /* rotate around shortest angle */
767  if ((1.0f + cosom) > 0.0001f) {
768 
769  if ((1.0f - cosom) > 0.0001f) {
770  omega = (float)acos(cosom);
771  sinom = sinf(omega);
772  sc1 = sinf((1.0 - t) * omega) / sinom;
773  sc2 = sinf(t * omega) / sinom;
774  }
775  else {
776  sc1 = 1.0f - t;
777  sc2 = t;
778  }
779  result[0] = sc1 * quat1[0] + sc2 * quat2[0];
780  result[1] = sc1 * quat1[1] + sc2 * quat2[1];
781  result[2] = sc1 * quat1[2] + sc2 * quat2[2];
782  result[3] = sc1 * quat1[3] + sc2 * quat2[3];
783  }
784  else {
785  result[0] = quat2[3];
786  result[1] = -quat2[2];
787  result[2] = quat2[1];
788  result[3] = -quat2[0];
789 
790  sc1 = sinf((1.0 - t) * M_PI_2);
791  sc2 = sinf(t * M_PI_2);
792 
793  result[0] = sc1 * quat1[0] + sc2 * result[0];
794  result[1] = sc1 * quat1[1] + sc2 * result[1];
795  result[2] = sc1 * quat1[2] + sc2 * result[2];
796  result[3] = sc1 * quat1[3] + sc2 * result[3];
797  }
798 }
799 #endif
800 
801 void interp_dot_slerp(const float t, const float cosom, float r_w[2])
802 {
803  const float eps = 1e-4f;
804 
805  BLI_assert(IN_RANGE_INCL(cosom, -1.0001f, 1.0001f));
806 
807  /* within [-1..1] range, avoid aligned axis */
808  if (LIKELY(fabsf(cosom) < (1.0f - eps))) {
809  float omega, sinom;
810 
811  omega = acosf(cosom);
812  sinom = sinf(omega);
813  r_w[0] = sinf((1.0f - t) * omega) / sinom;
814  r_w[1] = sinf(t * omega) / sinom;
815  }
816  else {
817  /* fallback to lerp */
818  r_w[0] = 1.0f - t;
819  r_w[1] = t;
820  }
821 }
822 
823 void interp_qt_qtqt(float q[4], const float a[4], const float b[4], const float t)
824 {
825  float quat[4], cosom, w[2];
826 
829 
830  cosom = dot_qtqt(a, b);
831 
832  /* rotate around shortest angle */
833  if (cosom < 0.0f) {
834  cosom = -cosom;
835  negate_v4_v4(quat, a);
836  }
837  else {
838  copy_qt_qt(quat, a);
839  }
840 
841  interp_dot_slerp(t, cosom, w);
842 
843  q[0] = w[0] * quat[0] + w[1] * b[0];
844  q[1] = w[0] * quat[1] + w[1] * b[1];
845  q[2] = w[0] * quat[2] + w[1] * b[2];
846  q[3] = w[0] * quat[3] + w[1] * b[3];
847 }
848 
849 void add_qt_qtqt(float q[4], const float a[4], const float b[4], const float t)
850 {
851  q[0] = a[0] + t * b[0];
852  q[1] = a[1] + t * b[1];
853  q[2] = a[2] + t * b[2];
854  q[3] = a[3] + t * b[3];
855 }
856 
858  float quat[4], const float v1[3], const float v2[3], const float v3[3], const float no_orig[3])
859 {
860  /* imaginary x-axis, y-axis triangle is being rotated */
861  float vec[3], q1[4], q2[4], n[3], si, co, angle, mat[3][3], imat[3][3];
862 
863  /* move z-axis to face-normal */
864 #if 0
865  normal_tri_v3(vec, v1, v2, v3);
866 #else
867  copy_v3_v3(vec, no_orig);
868  (void)v3;
869 #endif
870 
871  n[0] = vec[1];
872  n[1] = -vec[0];
873  n[2] = 0.0f;
874  normalize_v3(n);
875 
876  if (n[0] == 0.0f && n[1] == 0.0f) {
877  n[0] = 1.0f;
878  }
879 
880  angle = -0.5f * saacos(vec[2]);
881  co = cosf(angle);
882  si = sinf(angle);
883  q1[0] = co;
884  q1[1] = n[0] * si;
885  q1[2] = n[1] * si;
886  q1[3] = 0.0f;
887 
888  /* rotate back line v1-v2 */
889  quat_to_mat3(mat, q1);
890  invert_m3_m3(imat, mat);
891  sub_v3_v3v3(vec, v2, v1);
892  mul_m3_v3(imat, vec);
893 
894  /* what angle has this line with x-axis? */
895  vec[2] = 0.0f;
896  normalize_v3(vec);
897 
898  angle = 0.5f * atan2f(vec[1], vec[0]);
899  co = cosf(angle);
900  si = sinf(angle);
901  q2[0] = co;
902  q2[1] = 0.0f;
903  q2[2] = 0.0f;
904  q2[3] = si;
905 
906  mul_qt_qtqt(quat, q1, q2);
907 }
908 
909 float tri_to_quat(float q[4], const float a[3], const float b[3], const float c[3])
910 {
911  float vec[3];
912  const float len = normal_tri_v3(vec, a, b, c);
913 
914  tri_to_quat_ex(q, a, b, c, vec);
915  return len;
916 }
917 
918 void sin_cos_from_fraction(int numerator, const int denominator, float *r_sin, float *r_cos)
919 {
920  /* By default, creating an circle from an integer: calling #sinf & #cosf on the fraction doesn't
921  * create symmetrical values (because of float imprecision).
922  * Resolve this when the rotation is calculated from a fraction by mapping the `numerator`
923  * to lower values so X/Y values for points around a circle are exactly symmetrical, see T87779.
924  *
925  * - Numbers divisible by 4 are mapped to the lower 8th (8 axis symmetry).
926  * - Even numbers are mapped to the lower quarter (4 axis symmetry).
927  * - Odd numbers are mapped to the lower half (1 axis symmetry).
928  *
929  * Once the values are calculated, the are mapped back to their position in the circle
930  * using negation & swapping values. */
931 
932  BLI_assert((numerator <= denominator) && (denominator > 0));
933  enum { NEGATE_SIN_BIT = 0, NEGATE_COS_BIT = 1, SWAP_SIN_COS_BIT = 2 };
934  enum {
935  NEGATE_SIN = (1 << NEGATE_SIN_BIT),
936  NEGATE_COS = (1 << NEGATE_COS_BIT),
937  SWAP_SIN_COS = (1 << SWAP_SIN_COS_BIT),
938  } xform = 0;
939  if ((denominator & 3) == 0) {
940  /* The denominator divides by 4, determine the quadrant then further refine the upper 8th. */
941  const int denominator_4 = denominator / 4;
942  if (numerator < denominator_4) {
943  /* Fall through. */
944  }
945  else {
946  if (numerator < denominator_4 * 2) {
947  numerator -= denominator_4;
948  xform = NEGATE_SIN | SWAP_SIN_COS;
949  }
950  else if (numerator == denominator_4 * 2) {
951  numerator = 0;
952  xform = NEGATE_COS;
953  }
954  else if (numerator < denominator_4 * 3) {
955  numerator -= denominator_4 * 2;
956  xform = NEGATE_SIN | NEGATE_COS;
957  }
958  else if (numerator == denominator_4 * 3) {
959  numerator = 0;
960  xform = NEGATE_COS | SWAP_SIN_COS;
961  }
962  else {
963  numerator -= denominator_4 * 3;
964  xform = NEGATE_COS | SWAP_SIN_COS;
965  }
966  }
967  /* Further increase accuracy by using the range of the upper 8th. */
968  const int numerator_test = denominator_4 - numerator;
969  if (numerator_test < numerator) {
970  numerator = numerator_test;
971  xform ^= SWAP_SIN_COS;
972  /* Swap #NEGATE_SIN, #NEGATE_COS flags. */
973  xform = (xform & (uint)(~(NEGATE_SIN | NEGATE_COS))) |
974  (((xform & NEGATE_SIN) >> NEGATE_SIN_BIT) << NEGATE_COS_BIT) |
975  (((xform & NEGATE_COS) >> NEGATE_COS_BIT) << NEGATE_SIN_BIT);
976  }
977  }
978  else if ((denominator & 1) == 0) {
979  /* The denominator divides by 2, determine the quadrant then further refine the upper 4th. */
980  const int denominator_2 = denominator / 2;
981  if (numerator < denominator_2) {
982  /* Fall through. */
983  }
984  else if (numerator == denominator_2) {
985  numerator = 0;
986  xform = NEGATE_COS;
987  }
988  else {
989  numerator -= denominator_2;
990  xform = NEGATE_SIN | NEGATE_COS;
991  }
992  /* Further increase accuracy by using the range of the upper 4th. */
993  const int numerator_test = denominator_2 - numerator;
994  if (numerator_test < numerator) {
995  numerator = numerator_test;
996  xform ^= NEGATE_COS;
997  }
998  }
999  else {
1000  /* The denominator is an odd number, only refine the upper half. */
1001  const int numerator_test = denominator - numerator;
1002  if (numerator_test < numerator) {
1003  numerator = numerator_test;
1004  xform ^= NEGATE_SIN;
1005  }
1006  }
1007 
1008  const float phi = (float)(2.0 * M_PI) * ((float)numerator / (float)denominator);
1009  const float sin_phi = sinf(phi) * ((xform & NEGATE_SIN) ? -1.0f : 1.0f);
1010  const float cos_phi = cosf(phi) * ((xform & NEGATE_COS) ? -1.0f : 1.0f);
1011  if ((xform & SWAP_SIN_COS) == 0) {
1012  *r_sin = sin_phi;
1013  *r_cos = cos_phi;
1014  }
1015  else {
1016  *r_sin = cos_phi;
1017  *r_cos = sin_phi;
1018  }
1019 }
1020 
1021 void print_qt(const char *str, const float q[4])
1022 {
1023  printf("%s: %.3f %.3f %.3f %.3f\n", str, q[0], q[1], q[2], q[3]);
1024 }
1025 
1026 /******************************** Axis Angle *********************************/
1027 
1028 void axis_angle_normalized_to_quat(float r[4], const float axis[3], const float angle)
1029 {
1030  const float phi = 0.5f * angle;
1031  const float si = sinf(phi);
1032  const float co = cosf(phi);
1033  BLI_ASSERT_UNIT_V3(axis);
1034  r[0] = co;
1035  mul_v3_v3fl(r + 1, axis, si);
1036 }
1037 
1038 void axis_angle_to_quat(float r[4], const float axis[3], const float angle)
1039 {
1040  float nor[3];
1041 
1042  if (LIKELY(normalize_v3_v3(nor, axis) != 0.0f)) {
1044  }
1045  else {
1046  unit_qt(r);
1047  }
1048 }
1049 
1050 void quat_to_axis_angle(float axis[3], float *angle, const float q[4])
1051 {
1052  float ha, si;
1053 
1054 #ifdef DEBUG
1055  if (!((ha = dot_qtqt(q, q)) == 0.0f || (fabsf(ha - 1.0f) < (float)QUAT_EPSILON))) {
1056  fprintf(stderr,
1057  "Warning! quat_to_axis_angle() called with non-normalized: size %.8f *** report a bug "
1058  "***\n",
1059  ha);
1060  }
1061 #endif
1062 
1063  /* calculate angle/2, and sin(angle/2) */
1064  ha = acosf(q[0]);
1065  si = sinf(ha);
1066 
1067  /* from half-angle to angle */
1068  *angle = ha * 2;
1069 
1070  /* prevent division by zero for axis conversion */
1071  if (fabsf(si) < 0.0005f) {
1072  si = 1.0f;
1073  }
1074 
1075  axis[0] = q[1] / si;
1076  axis[1] = q[2] / si;
1077  axis[2] = q[3] / si;
1078  if (is_zero_v3(axis)) {
1079  axis[1] = 1.0f;
1080  }
1081 }
1082 
1083 void axis_angle_to_eulO(float eul[3], const short order, const float axis[3], const float angle)
1084 {
1085  float q[4];
1086 
1087  /* use quaternions as intermediate representation for now... */
1088  axis_angle_to_quat(q, axis, angle);
1089  quat_to_eulO(eul, order, q);
1090 }
1091 
1092 void eulO_to_axis_angle(float axis[3], float *angle, const float eul[3], const short order)
1093 {
1094  float q[4];
1095 
1096  /* use quaternions as intermediate representation for now... */
1097  eulO_to_quat(q, eul, order);
1098  quat_to_axis_angle(axis, angle, q);
1099 }
1100 
1102  const float axis[3],
1103  const float angle_sin,
1104  const float angle_cos)
1105 {
1106  float nsi[3], ico;
1107  float n_00, n_01, n_11, n_02, n_12, n_22;
1108 
1109  BLI_ASSERT_UNIT_V3(axis);
1110 
1111  /* now convert this to a 3x3 matrix */
1112 
1113  ico = (1.0f - angle_cos);
1114  nsi[0] = axis[0] * angle_sin;
1115  nsi[1] = axis[1] * angle_sin;
1116  nsi[2] = axis[2] * angle_sin;
1117 
1118  n_00 = (axis[0] * axis[0]) * ico;
1119  n_01 = (axis[0] * axis[1]) * ico;
1120  n_11 = (axis[1] * axis[1]) * ico;
1121  n_02 = (axis[0] * axis[2]) * ico;
1122  n_12 = (axis[1] * axis[2]) * ico;
1123  n_22 = (axis[2] * axis[2]) * ico;
1124 
1125  mat[0][0] = n_00 + angle_cos;
1126  mat[0][1] = n_01 + nsi[2];
1127  mat[0][2] = n_02 - nsi[1];
1128  mat[1][0] = n_01 - nsi[2];
1129  mat[1][1] = n_11 + angle_cos;
1130  mat[1][2] = n_12 + nsi[0];
1131  mat[2][0] = n_02 + nsi[1];
1132  mat[2][1] = n_12 - nsi[0];
1133  mat[2][2] = n_22 + angle_cos;
1134 }
1135 
1136 void axis_angle_normalized_to_mat3(float R[3][3], const float axis[3], const float angle)
1137 {
1139 }
1140 
1141 void axis_angle_to_mat3(float R[3][3], const float axis[3], const float angle)
1142 {
1143  float nor[3];
1144 
1145  /* normalize the axis first (to remove unwanted scaling) */
1146  if (normalize_v3_v3(nor, axis) == 0.0f) {
1147  unit_m3(R);
1148  return;
1149  }
1150 
1152 }
1153 
1154 void axis_angle_to_mat4(float R[4][4], const float axis[3], const float angle)
1155 {
1156  float tmat[3][3];
1157 
1158  axis_angle_to_mat3(tmat, axis, angle);
1159  unit_m4(R);
1160  copy_m4_m3(R, tmat);
1161 }
1162 
1163 void mat3_normalized_to_axis_angle(float axis[3], float *angle, const float mat[3][3])
1164 {
1165  float q[4];
1166 
1167  /* use quaternions as intermediate representation */
1168  /* TODO: it would be nicer to go straight there... */
1169  mat3_normalized_to_quat(q, mat);
1170  quat_to_axis_angle(axis, angle, q);
1171 }
1172 void mat3_to_axis_angle(float axis[3], float *angle, const float mat[3][3])
1173 {
1174  float q[4];
1175 
1176  /* use quaternions as intermediate representation */
1177  /* TODO: it would be nicer to go straight there... */
1178  mat3_to_quat(q, mat);
1179  quat_to_axis_angle(axis, angle, q);
1180 }
1181 
1182 void mat4_normalized_to_axis_angle(float axis[3], float *angle, const float mat[4][4])
1183 {
1184  float q[4];
1185 
1186  /* use quaternions as intermediate representation */
1187  /* TODO: it would be nicer to go straight there... */
1188  mat4_normalized_to_quat(q, mat);
1189  quat_to_axis_angle(axis, angle, q);
1190 }
1191 
1192 void mat4_to_axis_angle(float axis[3], float *angle, const float mat[4][4])
1193 {
1194  float q[4];
1195 
1196  /* use quaternions as intermediate representation */
1197  /* TODO: it would be nicer to go straight there... */
1198  mat4_to_quat(q, mat);
1199  quat_to_axis_angle(axis, angle, q);
1200 }
1201 
1202 void axis_angle_to_mat4_single(float R[4][4], const char axis, const float angle)
1203 {
1204  float mat3[3][3];
1205  axis_angle_to_mat3_single(mat3, axis, angle);
1206  copy_m4_m3(R, mat3);
1207 }
1208 
1209 void axis_angle_to_mat3_single(float R[3][3], const char axis, const float angle)
1210 {
1211  const float angle_cos = cosf(angle);
1212  const float angle_sin = sinf(angle);
1213 
1214  switch (axis) {
1215  case 'X': /* rotation around X */
1216  R[0][0] = 1.0f;
1217  R[0][1] = 0.0f;
1218  R[0][2] = 0.0f;
1219  R[1][0] = 0.0f;
1220  R[1][1] = angle_cos;
1221  R[1][2] = angle_sin;
1222  R[2][0] = 0.0f;
1223  R[2][1] = -angle_sin;
1224  R[2][2] = angle_cos;
1225  break;
1226  case 'Y': /* rotation around Y */
1227  R[0][0] = angle_cos;
1228  R[0][1] = 0.0f;
1229  R[0][2] = -angle_sin;
1230  R[1][0] = 0.0f;
1231  R[1][1] = 1.0f;
1232  R[1][2] = 0.0f;
1233  R[2][0] = angle_sin;
1234  R[2][1] = 0.0f;
1235  R[2][2] = angle_cos;
1236  break;
1237  case 'Z': /* rotation around Z */
1238  R[0][0] = angle_cos;
1239  R[0][1] = angle_sin;
1240  R[0][2] = 0.0f;
1241  R[1][0] = -angle_sin;
1242  R[1][1] = angle_cos;
1243  R[1][2] = 0.0f;
1244  R[2][0] = 0.0f;
1245  R[2][1] = 0.0f;
1246  R[2][2] = 1.0f;
1247  break;
1248  default:
1250  break;
1251  }
1252 }
1253 
1254 void angle_to_mat2(float R[2][2], const float angle)
1255 {
1256  const float angle_cos = cosf(angle);
1257  const float angle_sin = sinf(angle);
1258 
1259  /* 2D rotation matrix */
1260  R[0][0] = angle_cos;
1261  R[0][1] = angle_sin;
1262  R[1][0] = -angle_sin;
1263  R[1][1] = angle_cos;
1264 }
1265 
1266 void axis_angle_to_quat_single(float q[4], const char axis, const float angle)
1267 {
1268  const float angle_half = angle * 0.5f;
1269  const float angle_cos = cosf(angle_half);
1270  const float angle_sin = sinf(angle_half);
1271  const int axis_index = (axis - 'X');
1272 
1273  BLI_assert(axis >= 'X' && axis <= 'Z');
1274 
1275  q[0] = angle_cos;
1276  zero_v3(q + 1);
1277  q[axis_index + 1] = angle_sin;
1278 }
1279 
1280 /****************************** Exponential Map ******************************/
1281 
1282 void quat_normalized_to_expmap(float expmap[3], const float q[4])
1283 {
1284  float angle;
1286 
1287  /* Obtain axis/angle representation. */
1288  quat_to_axis_angle(expmap, &angle, q);
1289 
1290  /* Convert to exponential map. */
1291  mul_v3_fl(expmap, angle);
1292 }
1293 
1294 void quat_to_expmap(float expmap[3], const float q[4])
1295 {
1296  float q_no[4];
1297  normalize_qt_qt(q_no, q);
1298  quat_normalized_to_expmap(expmap, q_no);
1299 }
1300 
1301 void expmap_to_quat(float r[4], const float expmap[3])
1302 {
1303  float axis[3];
1304  float angle;
1305 
1306  /* Obtain axis/angle representation. */
1307  if (LIKELY((angle = normalize_v3_v3(axis, expmap)) != 0.0f)) {
1309  }
1310  else {
1311  unit_qt(r);
1312  }
1313 }
1314 
1315 /******************************** XYZ Eulers *********************************/
1316 
1317 void eul_to_mat3(float mat[3][3], const float eul[3])
1318 {
1319  double ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
1320 
1321  ci = cos(eul[0]);
1322  cj = cos(eul[1]);
1323  ch = cos(eul[2]);
1324  si = sin(eul[0]);
1325  sj = sin(eul[1]);
1326  sh = sin(eul[2]);
1327  cc = ci * ch;
1328  cs = ci * sh;
1329  sc = si * ch;
1330  ss = si * sh;
1331 
1332  mat[0][0] = (float)(cj * ch);
1333  mat[1][0] = (float)(sj * sc - cs);
1334  mat[2][0] = (float)(sj * cc + ss);
1335  mat[0][1] = (float)(cj * sh);
1336  mat[1][1] = (float)(sj * ss + cc);
1337  mat[2][1] = (float)(sj * cs - sc);
1338  mat[0][2] = (float)-sj;
1339  mat[1][2] = (float)(cj * si);
1340  mat[2][2] = (float)(cj * ci);
1341 }
1342 
1343 void eul_to_mat4(float mat[4][4], const float eul[3])
1344 {
1345  double ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
1346 
1347  ci = cos(eul[0]);
1348  cj = cos(eul[1]);
1349  ch = cos(eul[2]);
1350  si = sin(eul[0]);
1351  sj = sin(eul[1]);
1352  sh = sin(eul[2]);
1353  cc = ci * ch;
1354  cs = ci * sh;
1355  sc = si * ch;
1356  ss = si * sh;
1357 
1358  mat[0][0] = (float)(cj * ch);
1359  mat[1][0] = (float)(sj * sc - cs);
1360  mat[2][0] = (float)(sj * cc + ss);
1361  mat[0][1] = (float)(cj * sh);
1362  mat[1][1] = (float)(sj * ss + cc);
1363  mat[2][1] = (float)(sj * cs - sc);
1364  mat[0][2] = (float)-sj;
1365  mat[1][2] = (float)(cj * si);
1366  mat[2][2] = (float)(cj * ci);
1367 
1368  mat[3][0] = mat[3][1] = mat[3][2] = mat[0][3] = mat[1][3] = mat[2][3] = 0.0f;
1369  mat[3][3] = 1.0f;
1370 }
1371 
1372 /* returns two euler calculation methods, so we can pick the best */
1373 
1374 /* XYZ order */
1375 static void mat3_normalized_to_eul2(const float mat[3][3], float eul1[3], float eul2[3])
1376 {
1377  const float cy = hypotf(mat[0][0], mat[0][1]);
1378 
1379  BLI_ASSERT_UNIT_M3(mat);
1380 
1381  if (cy > 16.0f * FLT_EPSILON) {
1382 
1383  eul1[0] = atan2f(mat[1][2], mat[2][2]);
1384  eul1[1] = atan2f(-mat[0][2], cy);
1385  eul1[2] = atan2f(mat[0][1], mat[0][0]);
1386 
1387  eul2[0] = atan2f(-mat[1][2], -mat[2][2]);
1388  eul2[1] = atan2f(-mat[0][2], -cy);
1389  eul2[2] = atan2f(-mat[0][1], -mat[0][0]);
1390  }
1391  else {
1392  eul1[0] = atan2f(-mat[2][1], mat[1][1]);
1393  eul1[1] = atan2f(-mat[0][2], cy);
1394  eul1[2] = 0.0f;
1395 
1396  copy_v3_v3(eul2, eul1);
1397  }
1398 }
1399 
1400 void mat3_normalized_to_eul(float eul[3], const float mat[3][3])
1401 {
1402  float eul1[3], eul2[3];
1403 
1404  mat3_normalized_to_eul2(mat, eul1, eul2);
1405 
1406  /* return best, which is just the one with lowest values it in */
1407  if (fabsf(eul1[0]) + fabsf(eul1[1]) + fabsf(eul1[2]) >
1408  fabsf(eul2[0]) + fabsf(eul2[1]) + fabsf(eul2[2])) {
1409  copy_v3_v3(eul, eul2);
1410  }
1411  else {
1412  copy_v3_v3(eul, eul1);
1413  }
1414 }
1415 void mat3_to_eul(float eul[3], const float mat[3][3])
1416 {
1417  float unit_mat[3][3];
1418  normalize_m3_m3(unit_mat, mat);
1419  mat3_normalized_to_eul(eul, unit_mat);
1420 }
1421 
1422 void mat4_normalized_to_eul(float eul[3], const float m[4][4])
1423 {
1424  float mat3[3][3];
1425  copy_m3_m4(mat3, m);
1426  mat3_normalized_to_eul(eul, mat3);
1427 }
1428 void mat4_to_eul(float eul[3], const float m[4][4])
1429 {
1430  float mat3[3][3];
1431  copy_m3_m4(mat3, m);
1432  mat3_to_eul(eul, mat3);
1433 }
1434 
1435 void quat_to_eul(float eul[3], const float quat[4])
1436 {
1437  float unit_mat[3][3];
1438  quat_to_mat3(unit_mat, quat);
1439  mat3_normalized_to_eul(eul, unit_mat);
1440 }
1441 
1442 void eul_to_quat(float quat[4], const float eul[3])
1443 {
1444  float ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
1445 
1446  ti = eul[0] * 0.5f;
1447  tj = eul[1] * 0.5f;
1448  th = eul[2] * 0.5f;
1449  ci = cosf(ti);
1450  cj = cosf(tj);
1451  ch = cosf(th);
1452  si = sinf(ti);
1453  sj = sinf(tj);
1454  sh = sinf(th);
1455  cc = ci * ch;
1456  cs = ci * sh;
1457  sc = si * ch;
1458  ss = si * sh;
1459 
1460  quat[0] = cj * cc + sj * ss;
1461  quat[1] = cj * sc - sj * cs;
1462  quat[2] = cj * ss + sj * cc;
1463  quat[3] = cj * cs - sj * sc;
1464 }
1465 
1466 void rotate_eul(float beul[3], const char axis, const float ang)
1467 {
1468  float eul[3], mat1[3][3], mat2[3][3], totmat[3][3];
1469 
1470  BLI_assert(axis >= 'X' && axis <= 'Z');
1471 
1472  eul[0] = eul[1] = eul[2] = 0.0f;
1473  if (axis == 'X') {
1474  eul[0] = ang;
1475  }
1476  else if (axis == 'Y') {
1477  eul[1] = ang;
1478  }
1479  else {
1480  eul[2] = ang;
1481  }
1482 
1483  eul_to_mat3(mat1, eul);
1484  eul_to_mat3(mat2, beul);
1485 
1486  mul_m3_m3m3(totmat, mat2, mat1);
1487 
1488  mat3_to_eul(beul, totmat);
1489 }
1490 
1491 void compatible_eul(float eul[3], const float oldrot[3])
1492 {
1493  /* we could use M_PI as pi_thresh: which is correct but 5.1 gives better results.
1494  * Checked with baking actions to fcurves - campbell */
1495  const float pi_thresh = (5.1f);
1496  const float pi_x2 = (2.0f * (float)M_PI);
1497 
1498  float deul[3];
1499  unsigned int i;
1500 
1501  /* correct differences of about 360 degrees first */
1502  for (i = 0; i < 3; i++) {
1503  deul[i] = eul[i] - oldrot[i];
1504  if (deul[i] > pi_thresh) {
1505  eul[i] -= floorf((deul[i] / pi_x2) + 0.5f) * pi_x2;
1506  deul[i] = eul[i] - oldrot[i];
1507  }
1508  else if (deul[i] < -pi_thresh) {
1509  eul[i] += floorf((-deul[i] / pi_x2) + 0.5f) * pi_x2;
1510  deul[i] = eul[i] - oldrot[i];
1511  }
1512  }
1513 
1514  /* is 1 of the axis rotations larger than 180 degrees and the other small? NO ELSE IF!! */
1515  if (fabsf(deul[0]) > 3.2f && fabsf(deul[1]) < 1.6f && fabsf(deul[2]) < 1.6f) {
1516  if (deul[0] > 0.0f) {
1517  eul[0] -= pi_x2;
1518  }
1519  else {
1520  eul[0] += pi_x2;
1521  }
1522  }
1523  if (fabsf(deul[1]) > 3.2f && fabsf(deul[2]) < 1.6f && fabsf(deul[0]) < 1.6f) {
1524  if (deul[1] > 0.0f) {
1525  eul[1] -= pi_x2;
1526  }
1527  else {
1528  eul[1] += pi_x2;
1529  }
1530  }
1531  if (fabsf(deul[2]) > 3.2f && fabsf(deul[0]) < 1.6f && fabsf(deul[1]) < 1.6f) {
1532  if (deul[2] > 0.0f) {
1533  eul[2] -= pi_x2;
1534  }
1535  else {
1536  eul[2] += pi_x2;
1537  }
1538  }
1539 }
1540 
1541 /* uses 2 methods to retrieve eulers, and picks the closest */
1542 
1543 void mat3_normalized_to_compatible_eul(float eul[3], const float oldrot[3], float mat[3][3])
1544 {
1545  float eul1[3], eul2[3];
1546  float d1, d2;
1547 
1548  mat3_normalized_to_eul2(mat, eul1, eul2);
1549 
1550  compatible_eul(eul1, oldrot);
1551  compatible_eul(eul2, oldrot);
1552 
1553  d1 = fabsf(eul1[0] - oldrot[0]) + fabsf(eul1[1] - oldrot[1]) + fabsf(eul1[2] - oldrot[2]);
1554  d2 = fabsf(eul2[0] - oldrot[0]) + fabsf(eul2[1] - oldrot[1]) + fabsf(eul2[2] - oldrot[2]);
1555 
1556  /* return best, which is just the one with lowest difference */
1557  if (d1 > d2) {
1558  copy_v3_v3(eul, eul2);
1559  }
1560  else {
1561  copy_v3_v3(eul, eul1);
1562  }
1563 }
1564 void mat3_to_compatible_eul(float eul[3], const float oldrot[3], float mat[3][3])
1565 {
1566  float unit_mat[3][3];
1567  normalize_m3_m3(unit_mat, mat);
1568  mat3_normalized_to_compatible_eul(eul, oldrot, unit_mat);
1569 }
1570 
1571 void quat_to_compatible_eul(float eul[3], const float oldrot[3], const float quat[4])
1572 {
1573  float unit_mat[3][3];
1574  quat_to_mat3(unit_mat, quat);
1575  mat3_normalized_to_compatible_eul(eul, oldrot, unit_mat);
1576 }
1577 
1578 /************************** Arbitrary Order Eulers ***************************/
1579 
1580 /* Euler Rotation Order Code:
1581  * was adapted from
1582  * ANSI C code from the article
1583  * "Euler Angle Conversion"
1584  * by Ken Shoemake <shoemake@graphics.cis.upenn.edu>
1585  * in "Graphics Gems IV", Academic Press, 1994
1586  * for use in Blender
1587  */
1588 
1589 /* Type for rotation order info - see wiki for derivation details */
1590 typedef struct RotOrderInfo {
1591  short axis[3];
1592  short parity; /* parity of axis permutation (even=0, odd=1) - 'n' in original code */
1594 
1595 /* Array of info for Rotation Order calculations
1596  * WARNING: must be kept in same order as eEulerRotationOrders
1597  */
1598 static const RotOrderInfo rotOrders[] = {
1599  /* i, j, k, n */
1600  {{0, 1, 2}, 0}, /* XYZ */
1601  {{0, 2, 1}, 1}, /* XZY */
1602  {{1, 0, 2}, 1}, /* YXZ */
1603  {{1, 2, 0}, 0}, /* YZX */
1604  {{2, 0, 1}, 0}, /* ZXY */
1605  {{2, 1, 0}, 1} /* ZYX */
1606 };
1607 
1608 /* Get relevant pointer to rotation order set from the array
1609  * NOTE: since we start at 1 for the values, but arrays index from 0,
1610  * there is -1 factor involved in this process...
1611  */
1612 static const RotOrderInfo *get_rotation_order_info(const short order)
1613 {
1614  BLI_assert(order >= 0 && order <= 6);
1615  if (order < 1) {
1616  return &rotOrders[0];
1617  }
1618  if (order < 6) {
1619  return &rotOrders[order - 1];
1620  }
1621 
1622  return &rotOrders[5];
1623 }
1624 
1625 void eulO_to_quat(float q[4], const float e[3], const short order)
1626 {
1628  short i = R->axis[0], j = R->axis[1], k = R->axis[2];
1629  double ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
1630  double a[3];
1631 
1632  ti = e[i] * 0.5f;
1633  tj = e[j] * (R->parity ? -0.5f : 0.5f);
1634  th = e[k] * 0.5f;
1635 
1636  ci = cos(ti);
1637  cj = cos(tj);
1638  ch = cos(th);
1639  si = sin(ti);
1640  sj = sin(tj);
1641  sh = sin(th);
1642 
1643  cc = ci * ch;
1644  cs = ci * sh;
1645  sc = si * ch;
1646  ss = si * sh;
1647 
1648  a[i] = cj * sc - sj * cs;
1649  a[j] = cj * ss + sj * cc;
1650  a[k] = cj * cs - sj * sc;
1651 
1652  q[0] = (float)(cj * cc + sj * ss);
1653  q[1] = (float)(a[0]);
1654  q[2] = (float)(a[1]);
1655  q[3] = (float)(a[2]);
1656 
1657  if (R->parity) {
1658  q[j + 1] = -q[j + 1];
1659  }
1660 }
1661 
1662 void quat_to_eulO(float e[3], short const order, const float q[4])
1663 {
1664  float unit_mat[3][3];
1665 
1666  quat_to_mat3(unit_mat, q);
1667  mat3_normalized_to_eulO(e, order, unit_mat);
1668 }
1669 
1670 void eulO_to_mat3(float M[3][3], const float e[3], const short order)
1671 {
1673  short i = R->axis[0], j = R->axis[1], k = R->axis[2];
1674  double ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
1675 
1676  if (R->parity) {
1677  ti = -e[i];
1678  tj = -e[j];
1679  th = -e[k];
1680  }
1681  else {
1682  ti = e[i];
1683  tj = e[j];
1684  th = e[k];
1685  }
1686 
1687  ci = cos(ti);
1688  cj = cos(tj);
1689  ch = cos(th);
1690  si = sin(ti);
1691  sj = sin(tj);
1692  sh = sin(th);
1693 
1694  cc = ci * ch;
1695  cs = ci * sh;
1696  sc = si * ch;
1697  ss = si * sh;
1698 
1699  M[i][i] = (float)(cj * ch);
1700  M[j][i] = (float)(sj * sc - cs);
1701  M[k][i] = (float)(sj * cc + ss);
1702  M[i][j] = (float)(cj * sh);
1703  M[j][j] = (float)(sj * ss + cc);
1704  M[k][j] = (float)(sj * cs - sc);
1705  M[i][k] = (float)(-sj);
1706  M[j][k] = (float)(cj * si);
1707  M[k][k] = (float)(cj * ci);
1708 }
1709 
1710 /* returns two euler calculation methods, so we can pick the best */
1711 static void mat3_normalized_to_eulo2(const float mat[3][3],
1712  float eul1[3],
1713  float eul2[3],
1714  const short order)
1715 {
1717  short i = R->axis[0], j = R->axis[1], k = R->axis[2];
1718  float cy;
1719 
1720  BLI_ASSERT_UNIT_M3(mat);
1721 
1722  cy = hypotf(mat[i][i], mat[i][j]);
1723 
1724  if (cy > 16.0f * FLT_EPSILON) {
1725  eul1[i] = atan2f(mat[j][k], mat[k][k]);
1726  eul1[j] = atan2f(-mat[i][k], cy);
1727  eul1[k] = atan2f(mat[i][j], mat[i][i]);
1728 
1729  eul2[i] = atan2f(-mat[j][k], -mat[k][k]);
1730  eul2[j] = atan2f(-mat[i][k], -cy);
1731  eul2[k] = atan2f(-mat[i][j], -mat[i][i]);
1732  }
1733  else {
1734  eul1[i] = atan2f(-mat[k][j], mat[j][j]);
1735  eul1[j] = atan2f(-mat[i][k], cy);
1736  eul1[k] = 0;
1737 
1738  copy_v3_v3(eul2, eul1);
1739  }
1740 
1741  if (R->parity) {
1742  negate_v3(eul1);
1743  negate_v3(eul2);
1744  }
1745 }
1746 
1747 void eulO_to_mat4(float mat[4][4], const float e[3], const short order)
1748 {
1749  float unit_mat[3][3];
1750 
1751  /* for now, we'll just do this the slow way (i.e. copying matrices) */
1752  eulO_to_mat3(unit_mat, e, order);
1753  copy_m4_m3(mat, unit_mat);
1754 }
1755 
1756 void mat3_normalized_to_eulO(float eul[3], const short order, const float m[3][3])
1757 {
1758  float eul1[3], eul2[3];
1759  float d1, d2;
1760 
1761  mat3_normalized_to_eulo2(m, eul1, eul2, order);
1762 
1763  d1 = fabsf(eul1[0]) + fabsf(eul1[1]) + fabsf(eul1[2]);
1764  d2 = fabsf(eul2[0]) + fabsf(eul2[1]) + fabsf(eul2[2]);
1765 
1766  /* return best, which is just the one with lowest values it in */
1767  if (d1 > d2) {
1768  copy_v3_v3(eul, eul2);
1769  }
1770  else {
1771  copy_v3_v3(eul, eul1);
1772  }
1773 }
1774 void mat3_to_eulO(float eul[3], const short order, const float m[3][3])
1775 {
1776  float unit_mat[3][3];
1777  normalize_m3_m3(unit_mat, m);
1778  mat3_normalized_to_eulO(eul, order, unit_mat);
1779 }
1780 
1781 void mat4_normalized_to_eulO(float eul[3], const short order, const float m[4][4])
1782 {
1783  float mat3[3][3];
1784 
1785  /* for now, we'll just do this the slow way (i.e. copying matrices) */
1786  copy_m3_m4(mat3, m);
1787  mat3_normalized_to_eulO(eul, order, mat3);
1788 }
1789 
1790 void mat4_to_eulO(float eul[3], const short order, const float m[4][4])
1791 {
1792  float mat3[3][3];
1793  copy_m3_m4(mat3, m);
1794  normalize_m3(mat3);
1795  mat3_normalized_to_eulO(eul, order, mat3);
1796 }
1797 
1799  const float oldrot[3],
1800  const short order,
1801  const float mat[3][3])
1802 {
1803  float eul1[3], eul2[3];
1804  float d1, d2;
1805 
1806  mat3_normalized_to_eulo2(mat, eul1, eul2, order);
1807 
1808  compatible_eul(eul1, oldrot);
1809  compatible_eul(eul2, oldrot);
1810 
1811  d1 = fabsf(eul1[0] - oldrot[0]) + fabsf(eul1[1] - oldrot[1]) + fabsf(eul1[2] - oldrot[2]);
1812  d2 = fabsf(eul2[0] - oldrot[0]) + fabsf(eul2[1] - oldrot[1]) + fabsf(eul2[2] - oldrot[2]);
1813 
1814  /* return best, which is just the one with lowest difference */
1815  if (d1 > d2) {
1816  copy_v3_v3(eul, eul2);
1817  }
1818  else {
1819  copy_v3_v3(eul, eul1);
1820  }
1821 }
1822 void mat3_to_compatible_eulO(float eul[3],
1823  const float oldrot[3],
1824  const short order,
1825  const float mat[3][3])
1826 {
1827  float unit_mat[3][3];
1828 
1829  normalize_m3_m3(unit_mat, mat);
1830  mat3_normalized_to_compatible_eulO(eul, oldrot, order, unit_mat);
1831 }
1832 
1834  const float oldrot[3],
1835  const short order,
1836  const float m[4][4])
1837 {
1838  float mat3[3][3];
1839 
1840  /* for now, we'll just do this the slow way (i.e. copying matrices) */
1841  copy_m3_m4(mat3, m);
1842  mat3_normalized_to_compatible_eulO(eul, oldrot, order, mat3);
1843 }
1844 void mat4_to_compatible_eulO(float eul[3],
1845  const float oldrot[3],
1846  const short order,
1847  const float m[4][4])
1848 {
1849  float mat3[3][3];
1850 
1851  /* for now, we'll just do this the slow way (i.e. copying matrices) */
1852  copy_m3_m4(mat3, m);
1853  normalize_m3(mat3);
1854  mat3_normalized_to_compatible_eulO(eul, oldrot, order, mat3);
1855 }
1856 
1857 void quat_to_compatible_eulO(float eul[3],
1858  const float oldrot[3],
1859  const short order,
1860  const float quat[4])
1861 {
1862  float unit_mat[3][3];
1863 
1864  quat_to_mat3(unit_mat, quat);
1865  mat3_normalized_to_compatible_eulO(eul, oldrot, order, unit_mat);
1866 }
1867 
1868 /* rotate the given euler by the given angle on the specified axis */
1869 /* NOTE: is this safe to do with different axis orders? */
1870 
1871 void rotate_eulO(float beul[3], const short order, char axis, float ang)
1872 {
1873  float eul[3], mat1[3][3], mat2[3][3], totmat[3][3];
1874 
1875  BLI_assert(axis >= 'X' && axis <= 'Z');
1876 
1877  zero_v3(eul);
1878 
1879  if (axis == 'X') {
1880  eul[0] = ang;
1881  }
1882  else if (axis == 'Y') {
1883  eul[1] = ang;
1884  }
1885  else {
1886  eul[2] = ang;
1887  }
1888 
1889  eulO_to_mat3(mat1, eul, order);
1890  eulO_to_mat3(mat2, beul, order);
1891 
1892  mul_m3_m3m3(totmat, mat2, mat1);
1893 
1894  mat3_to_eulO(beul, order, totmat);
1895 }
1896 
1897 void eulO_to_gimbal_axis(float gmat[3][3], const float eul[3], const short order)
1898 {
1900 
1901  float mat[3][3];
1902  float teul[3];
1903 
1904  /* first axis is local */
1905  eulO_to_mat3(mat, eul, order);
1906  copy_v3_v3(gmat[R->axis[0]], mat[R->axis[0]]);
1907 
1908  /* second axis is local minus first rotation */
1909  copy_v3_v3(teul, eul);
1910  teul[R->axis[0]] = 0;
1911  eulO_to_mat3(mat, teul, order);
1912  copy_v3_v3(gmat[R->axis[1]], mat[R->axis[1]]);
1913 
1914  /* Last axis is global */
1915  zero_v3(gmat[R->axis[2]]);
1916  gmat[R->axis[2]][R->axis[2]] = 1;
1917 }
1918 
1919 void add_eul_euleul(float r_eul[3], float a[3], float b[3], const short order)
1920 {
1921  float quat[4], quat_b[4];
1922 
1923  eulO_to_quat(quat, a, order);
1924  eulO_to_quat(quat_b, b, order);
1925 
1926  mul_qt_qtqt(quat, quat_b, quat);
1927 
1928  quat_to_eulO(r_eul, order, quat);
1929 }
1930 
1931 void sub_eul_euleul(float r_eul[3], float a[3], float b[3], const short order)
1932 {
1933  float quat[4], quat_b[4];
1934 
1935  eulO_to_quat(quat, a, order);
1936  eulO_to_quat(quat_b, b, order);
1937 
1938  invert_qt_normalized(quat_b);
1939  mul_qt_qtqt(quat, quat_b, quat);
1940 
1941  quat_to_eulO(r_eul, order, quat);
1942 }
1943 
1944 /******************************* Dual Quaternions ****************************/
1945 
1946 /* Conversion routines between (regular quaternion, translation) and dual quaternion.
1947  *
1948  * Version 1.0.0, February 7th, 2007
1949  *
1950  * SPDX-License-Identifier: Zlib
1951  * Copyright 2006-2007 University of Dublin, Trinity College, All Rights Reserved.
1952  *
1953  * Changes for Blender:
1954  * - renaming, style changes and optimization's
1955  * - added support for scaling
1956  */
1957 
1958 void mat4_to_dquat(DualQuat *dq, const float basemat[4][4], const float mat[4][4])
1959 {
1960  float *t, *q, dscale[3], scale[3], basequat[4], mat3[3][3];
1961  float baseRS[4][4], baseinv[4][4], baseR[4][4], baseRinv[4][4];
1962  float R[4][4], S[4][4];
1963 
1964  /* split scaling and rotation, there is probably a faster way to do
1965  * this, it's done like this now to correctly get negative scaling */
1966  mul_m4_m4m4(baseRS, mat, basemat);
1967  mat4_to_size(scale, baseRS);
1968 
1969  dscale[0] = scale[0] - 1.0f;
1970  dscale[1] = scale[1] - 1.0f;
1971  dscale[2] = scale[2] - 1.0f;
1972 
1973  copy_m3_m4(mat3, mat);
1974 
1975  if (!is_orthonormal_m3(mat3) || (determinant_m4(mat) < 0.0f) ||
1976  len_squared_v3(dscale) > square_f(1e-4f)) {
1977  /* Extract R and S. */
1978  float tmp[4][4];
1979 
1980  /* extra orthogonalize, to avoid flipping with stretched bones */
1981  copy_m4_m4(tmp, baseRS);
1982  orthogonalize_m4(tmp, 1);
1983  mat4_to_quat(basequat, tmp);
1984 
1985  quat_to_mat4(baseR, basequat);
1986  copy_v3_v3(baseR[3], baseRS[3]);
1987 
1988  invert_m4_m4(baseinv, basemat);
1989  mul_m4_m4m4(R, baseR, baseinv);
1990 
1991  invert_m4_m4(baseRinv, baseR);
1992  mul_m4_m4m4(S, baseRinv, baseRS);
1993 
1994  /* set scaling part */
1995  mul_m4_series(dq->scale, basemat, S, baseinv);
1996  dq->scale_weight = 1.0f;
1997  }
1998  else {
1999  /* matrix does not contain scaling */
2000  copy_m4_m4(R, mat);
2001  dq->scale_weight = 0.0f;
2002  }
2003 
2004  /* non-dual part */
2005  mat4_to_quat(dq->quat, R);
2006 
2007  /* dual part */
2008  t = R[3];
2009  q = dq->quat;
2010  dq->trans[0] = -0.5f * (t[0] * q[1] + t[1] * q[2] + t[2] * q[3]);
2011  dq->trans[1] = 0.5f * (t[0] * q[0] + t[1] * q[3] - t[2] * q[2]);
2012  dq->trans[2] = 0.5f * (-t[0] * q[3] + t[1] * q[0] + t[2] * q[1]);
2013  dq->trans[3] = 0.5f * (t[0] * q[2] - t[1] * q[1] + t[2] * q[0]);
2014 }
2015 
2016 void dquat_to_mat4(float R[4][4], const DualQuat *dq)
2017 {
2018  float len, q0[4];
2019  const float *t;
2020 
2021  /* regular quaternion */
2022  copy_qt_qt(q0, dq->quat);
2023 
2024  /* normalize */
2025  len = sqrtf(dot_qtqt(q0, q0));
2026  if (len != 0.0f) {
2027  len = 1.0f / len;
2028  }
2029  mul_qt_fl(q0, len);
2030 
2031  /* rotation */
2032  quat_to_mat4(R, q0);
2033 
2034  /* translation */
2035  t = dq->trans;
2036  R[3][0] = 2.0f * (-t[0] * q0[1] + t[1] * q0[0] - t[2] * q0[3] + t[3] * q0[2]) * len;
2037  R[3][1] = 2.0f * (-t[0] * q0[2] + t[1] * q0[3] + t[2] * q0[0] - t[3] * q0[1]) * len;
2038  R[3][2] = 2.0f * (-t[0] * q0[3] - t[1] * q0[2] + t[2] * q0[1] + t[3] * q0[0]) * len;
2039 
2040  /* scaling */
2041  if (dq->scale_weight) {
2042  mul_m4_m4m4(R, R, dq->scale);
2043  }
2044 }
2045 
2046 void add_weighted_dq_dq(DualQuat *dq_sum, const DualQuat *dq, float weight)
2047 {
2048  bool flipped = false;
2049 
2050  /* make sure we interpolate quats in the right direction */
2051  if (dot_qtqt(dq->quat, dq_sum->quat) < 0) {
2052  flipped = true;
2053  weight = -weight;
2054  }
2055 
2056  /* interpolate rotation and translation */
2057  dq_sum->quat[0] += weight * dq->quat[0];
2058  dq_sum->quat[1] += weight * dq->quat[1];
2059  dq_sum->quat[2] += weight * dq->quat[2];
2060  dq_sum->quat[3] += weight * dq->quat[3];
2061 
2062  dq_sum->trans[0] += weight * dq->trans[0];
2063  dq_sum->trans[1] += weight * dq->trans[1];
2064  dq_sum->trans[2] += weight * dq->trans[2];
2065  dq_sum->trans[3] += weight * dq->trans[3];
2066 
2067  /* Interpolate scale - but only if there is scale present. If any dual
2068  * quaternions without scale are added, they will be compensated for in
2069  * normalize_dq. */
2070  if (dq->scale_weight) {
2071  float wmat[4][4];
2072 
2073  if (flipped) {
2074  /* we don't want negative weights for scaling */
2075  weight = -weight;
2076  }
2077 
2078  copy_m4_m4(wmat, (float(*)[4])dq->scale);
2079  mul_m4_fl(wmat, weight);
2080  add_m4_m4m4(dq_sum->scale, dq_sum->scale, wmat);
2081  dq_sum->scale_weight += weight;
2082  }
2083 }
2084 
2085 void normalize_dq(DualQuat *dq, float totweight)
2086 {
2087  const float scale = 1.0f / totweight;
2088 
2089  mul_qt_fl(dq->quat, scale);
2090  mul_qt_fl(dq->trans, scale);
2091 
2092  /* Handle scale if needed. */
2093  if (dq->scale_weight) {
2094  /* Compensate for any dual quaternions added without scale. This is an
2095  * optimization so that we can skip the scale part when not needed. */
2096  float addweight = totweight - dq->scale_weight;
2097 
2098  if (addweight) {
2099  dq->scale[0][0] += addweight;
2100  dq->scale[1][1] += addweight;
2101  dq->scale[2][2] += addweight;
2102  dq->scale[3][3] += addweight;
2103  }
2104 
2105  mul_m4_fl(dq->scale, scale);
2106  dq->scale_weight = 1.0f;
2107  }
2108 }
2109 
2110 void mul_v3m3_dq(float r[3], float R[3][3], DualQuat *dq)
2111 {
2112  float M[3][3], t[3], scalemat[3][3], len2;
2113  float w = dq->quat[0], x = dq->quat[1], y = dq->quat[2], z = dq->quat[3];
2114  float t0 = dq->trans[0], t1 = dq->trans[1], t2 = dq->trans[2], t3 = dq->trans[3];
2115 
2116  /* rotation matrix */
2117  M[0][0] = w * w + x * x - y * y - z * z;
2118  M[1][0] = 2 * (x * y - w * z);
2119  M[2][0] = 2 * (x * z + w * y);
2120 
2121  M[0][1] = 2 * (x * y + w * z);
2122  M[1][1] = w * w + y * y - x * x - z * z;
2123  M[2][1] = 2 * (y * z - w * x);
2124 
2125  M[0][2] = 2 * (x * z - w * y);
2126  M[1][2] = 2 * (y * z + w * x);
2127  M[2][2] = w * w + z * z - x * x - y * y;
2128 
2129  len2 = dot_qtqt(dq->quat, dq->quat);
2130  if (len2 > 0.0f) {
2131  len2 = 1.0f / len2;
2132  }
2133 
2134  /* translation */
2135  t[0] = 2 * (-t0 * x + w * t1 - t2 * z + y * t3);
2136  t[1] = 2 * (-t0 * y + t1 * z - x * t3 + w * t2);
2137  t[2] = 2 * (-t0 * z + x * t2 + w * t3 - t1 * y);
2138 
2139  /* apply scaling */
2140  if (dq->scale_weight) {
2141  mul_m4_v3(dq->scale, r);
2142  }
2143 
2144  /* apply rotation and translation */
2145  mul_m3_v3(M, r);
2146  r[0] = (r[0] + t[0]) * len2;
2147  r[1] = (r[1] + t[1]) * len2;
2148  r[2] = (r[2] + t[2]) * len2;
2149 
2150  /* Compute crazy-space correction matrix. */
2151  if (R) {
2152  if (dq->scale_weight) {
2153  copy_m3_m4(scalemat, dq->scale);
2154  mul_m3_m3m3(R, M, scalemat);
2155  }
2156  else {
2157  copy_m3_m3(R, M);
2158  }
2159  mul_m3_fl(R, len2);
2160  }
2161 }
2162 
2163 void copy_dq_dq(DualQuat *r, const DualQuat *dq)
2164 {
2165  memcpy(r, dq, sizeof(DualQuat));
2166 }
2167 
2168 void quat_apply_track(float quat[4], short axis, short upflag)
2169 {
2170  /* rotations are hard coded to match vec_to_quat */
2171  const float sqrt_1_2 = (float)M_SQRT1_2;
2172  const float quat_track[][4] = {
2173  /* pos-y90 */
2174  {sqrt_1_2, 0.0, -sqrt_1_2, 0.0},
2175  /* Quaternion((1,0,0), radians(90)) * Quaternion((0,1,0), radians(90)) */
2176  {0.5, 0.5, 0.5, 0.5},
2177  /* pos-z90 */
2178  {sqrt_1_2, 0.0, 0.0, sqrt_1_2},
2179  /* neg-y90 */
2180  {sqrt_1_2, 0.0, sqrt_1_2, 0.0},
2181  /* Quaternion((1,0,0), radians(-90)) * Quaternion((0,1,0), radians(-90)) */
2182  {0.5, -0.5, -0.5, 0.5},
2183  /* no rotation */
2184  {0.0, sqrt_1_2, sqrt_1_2, 0.0},
2185  };
2186 
2187  BLI_assert(axis >= 0 && axis <= 5);
2188  BLI_assert(upflag >= 0 && upflag <= 2);
2189 
2190  mul_qt_qtqt(quat, quat, quat_track[axis]);
2191 
2192  if (axis > 2) {
2193  axis = (short)(axis - 3);
2194  }
2195 
2196  /* there are 2 possible up-axis for each axis used, the 'quat_track' applies so the first
2197  * up axis is used X->Y, Y->X, Z->X, if this first up axis isn't used then rotate 90d
2198  * the strange bit shift below just find the low axis {X:Y, Y:X, Z:X} */
2199  if (upflag != (2 - axis) >> 1) {
2200  float q[4] = {sqrt_1_2, 0.0, 0.0, 0.0}; /* assign 90d rotation axis */
2201  q[axis + 1] = ((axis == 1)) ? sqrt_1_2 : -sqrt_1_2; /* flip non Y axis */
2202  mul_qt_qtqt(quat, quat, q);
2203  }
2204 }
2205 
2206 void vec_apply_track(float vec[3], short axis)
2207 {
2208  float tvec[3];
2209 
2210  BLI_assert(axis >= 0 && axis <= 5);
2211 
2212  copy_v3_v3(tvec, vec);
2213 
2214  switch (axis) {
2215  case 0: /* pos-x */
2216  /* vec[0] = 0.0; */
2217  vec[1] = tvec[2];
2218  vec[2] = -tvec[1];
2219  break;
2220  case 1: /* pos-y */
2221  /* vec[0] = tvec[0]; */
2222  /* vec[1] = 0.0; */
2223  /* vec[2] = tvec[2]; */
2224  break;
2225  case 2: /* pos-z */
2226  /* vec[0] = tvec[0]; */
2227  /* vec[1] = tvec[1]; */
2228  /* vec[2] = 0.0; */
2229  break;
2230  case 3: /* neg-x */
2231  /* vec[0] = 0.0; */
2232  vec[1] = tvec[2];
2233  vec[2] = -tvec[1];
2234  break;
2235  case 4: /* neg-y */
2236  vec[0] = -tvec[2];
2237  /* vec[1] = 0.0; */
2238  vec[2] = tvec[0];
2239  break;
2240  case 5: /* neg-z */
2241  vec[0] = -tvec[0];
2242  vec[1] = -tvec[1];
2243  /* vec[2] = 0.0; */
2244  break;
2245  }
2246 }
2247 
2248 float focallength_to_fov(float focal_length, float sensor)
2249 {
2250  return 2.0f * atanf((sensor / 2.0f) / focal_length);
2251 }
2252 
2253 float fov_to_focallength(float hfov, float sensor)
2254 {
2255  return (sensor / 2.0f) / tanf(hfov * 0.5f);
2256 }
2257 
2258 /* 'mod_inline(-3, 4)= 1', 'fmod(-3, 4)= -3' */
2259 static float mod_inline(float a, float b)
2260 {
2261  return a - (b * floorf(a / b));
2262 }
2263 
2264 float angle_wrap_rad(float angle)
2265 {
2266  return mod_inline(angle + (float)M_PI, (float)M_PI * 2.0f) - (float)M_PI;
2267 }
2268 
2269 float angle_wrap_deg(float angle)
2270 {
2271  return mod_inline(angle + 180.0f, 360.0f) - 180.0f;
2272 }
2273 
2274 float angle_compat_rad(float angle, float angle_compat)
2275 {
2276  return angle_compat + angle_wrap_rad(angle - angle_compat);
2277 }
2278 
2279 /* axis conversion */
2280 static float _axis_convert_matrix[23][3][3] = {
2281  {{-1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}},
2282  {{-1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, {0.0, -1.0, 0.0}},
2283  {{-1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 1.0, 0.0}},
2284  {{-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}},
2285  {{0.0, -1.0, 0.0}, {-1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}},
2286  {{0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}},
2287  {{0.0, 0.0, -1.0}, {-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}},
2288  {{0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}},
2289  {{0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}},
2290  {{0.0, 0.0, -1.0}, {0.0, -1.0, 0.0}, {-1.0, 0.0, 0.0}},
2291  {{0.0, 0.0, 1.0}, {0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}},
2292  {{0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, {-1.0, 0.0, 0.0}},
2293  {{0.0, -1.0, 0.0}, {0.0, 0.0, -1.0}, {1.0, 0.0, 0.0}},
2294  {{0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, {1.0, 0.0, 0.0}},
2295  {{0.0, 0.0, -1.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0}},
2296  {{0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {1.0, 0.0, 0.0}},
2297  {{0.0, -1.0, 0.0}, {1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}},
2298  {{0.0, 0.0, -1.0}, {1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}},
2299  {{0.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}},
2300  {{0.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}},
2301  {{1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, -1.0}},
2302  {{1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}},
2303  {{1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, {0.0, 1.0, 0.0}},
2304 };
2305 
2306 static int _axis_convert_lut[23][24] = {
2307  {0x8C8, 0x4D0, 0x2E0, 0xAE8, 0x701, 0x511, 0x119, 0xB29, 0x682, 0x88A, 0x09A, 0x2A2,
2308  0x80B, 0x413, 0x223, 0xA2B, 0x644, 0x454, 0x05C, 0xA6C, 0x745, 0x94D, 0x15D, 0x365},
2309  {0xAC8, 0x8D0, 0x4E0, 0x2E8, 0x741, 0x951, 0x159, 0x369, 0x702, 0xB0A, 0x11A, 0x522,
2310  0xA0B, 0x813, 0x423, 0x22B, 0x684, 0x894, 0x09C, 0x2AC, 0x645, 0xA4D, 0x05D, 0x465},
2311  {0x4C8, 0x2D0, 0xAE0, 0x8E8, 0x681, 0x291, 0x099, 0x8A9, 0x642, 0x44A, 0x05A, 0xA62,
2312  0x40B, 0x213, 0xA23, 0x82B, 0x744, 0x354, 0x15C, 0x96C, 0x705, 0x50D, 0x11D, 0xB25},
2313  {0x2C8, 0xAD0, 0x8E0, 0x4E8, 0x641, 0xA51, 0x059, 0x469, 0x742, 0x34A, 0x15A, 0x962,
2314  0x20B, 0xA13, 0x823, 0x42B, 0x704, 0xB14, 0x11C, 0x52C, 0x685, 0x28D, 0x09D, 0x8A5},
2315  {0x708, 0xB10, 0x120, 0x528, 0x8C1, 0xAD1, 0x2D9, 0x4E9, 0x942, 0x74A, 0x35A, 0x162,
2316  0x64B, 0xA53, 0x063, 0x46B, 0x804, 0xA14, 0x21C, 0x42C, 0x885, 0x68D, 0x29D, 0x0A5},
2317  {0xB08, 0x110, 0x520, 0x728, 0x941, 0x151, 0x359, 0x769, 0x802, 0xA0A, 0x21A, 0x422,
2318  0xA4B, 0x053, 0x463, 0x66B, 0x884, 0x094, 0x29C, 0x6AC, 0x8C5, 0xACD, 0x2DD, 0x4E5},
2319  {0x508, 0x710, 0xB20, 0x128, 0x881, 0x691, 0x299, 0x0A9, 0x8C2, 0x4CA, 0x2DA, 0xAE2,
2320  0x44B, 0x653, 0xA63, 0x06B, 0x944, 0x754, 0x35C, 0x16C, 0x805, 0x40D, 0x21D, 0xA25},
2321  {0x108, 0x510, 0x720, 0xB28, 0x801, 0x411, 0x219, 0xA29, 0x882, 0x08A, 0x29A, 0x6A2,
2322  0x04B, 0x453, 0x663, 0xA6B, 0x8C4, 0x4D4, 0x2DC, 0xAEC, 0x945, 0x14D, 0x35D, 0x765},
2323  {0x748, 0x350, 0x160, 0x968, 0xAC1, 0x2D1, 0x4D9, 0x8E9, 0xA42, 0x64A, 0x45A, 0x062,
2324  0x68B, 0x293, 0x0A3, 0x8AB, 0xA04, 0x214, 0x41C, 0x82C, 0xB05, 0x70D, 0x51D, 0x125},
2325  {0x948, 0x750, 0x360, 0x168, 0xB01, 0x711, 0x519, 0x129, 0xAC2, 0x8CA, 0x4DA, 0x2E2,
2326  0x88B, 0x693, 0x2A3, 0x0AB, 0xA44, 0x654, 0x45C, 0x06C, 0xA05, 0x80D, 0x41D, 0x225},
2327  {0x348, 0x150, 0x960, 0x768, 0xA41, 0x051, 0x459, 0x669, 0xA02, 0x20A, 0x41A, 0x822,
2328  0x28B, 0x093, 0x8A3, 0x6AB, 0xB04, 0x114, 0x51C, 0x72C, 0xAC5, 0x2CD, 0x4DD, 0x8E5},
2329  {0x148, 0x950, 0x760, 0x368, 0xA01, 0x811, 0x419, 0x229, 0xB02, 0x10A, 0x51A, 0x722,
2330  0x08B, 0x893, 0x6A3, 0x2AB, 0xAC4, 0x8D4, 0x4DC, 0x2EC, 0xA45, 0x04D, 0x45D, 0x665},
2331  {0x688, 0x890, 0x0A0, 0x2A8, 0x4C1, 0x8D1, 0xAD9, 0x2E9, 0x502, 0x70A, 0xB1A, 0x122,
2332  0x74B, 0x953, 0x163, 0x36B, 0x404, 0x814, 0xA1C, 0x22C, 0x445, 0x64D, 0xA5D, 0x065},
2333  {0x888, 0x090, 0x2A0, 0x6A8, 0x501, 0x111, 0xB19, 0x729, 0x402, 0x80A, 0xA1A, 0x222,
2334  0x94B, 0x153, 0x363, 0x76B, 0x444, 0x054, 0xA5C, 0x66C, 0x4C5, 0x8CD, 0xADD, 0x2E5},
2335  {0x288, 0x690, 0x8A0, 0x0A8, 0x441, 0x651, 0xA59, 0x069, 0x4C2, 0x2CA, 0xADA, 0x8E2,
2336  0x34B, 0x753, 0x963, 0x16B, 0x504, 0x714, 0xB1C, 0x12C, 0x405, 0x20D, 0xA1D, 0x825},
2337  {0x088, 0x290, 0x6A0, 0x8A8, 0x401, 0x211, 0xA19, 0x829, 0x442, 0x04A, 0xA5A, 0x662,
2338  0x14B, 0x353, 0x763, 0x96B, 0x4C4, 0x2D4, 0xADC, 0x8EC, 0x505, 0x10D, 0xB1D, 0x725},
2339  {0x648, 0x450, 0x060, 0xA68, 0x2C1, 0x4D1, 0x8D9, 0xAE9, 0x282, 0x68A, 0x89A, 0x0A2,
2340  0x70B, 0x513, 0x123, 0xB2B, 0x204, 0x414, 0x81C, 0xA2C, 0x345, 0x74D, 0x95D, 0x165},
2341  {0xA48, 0x650, 0x460, 0x068, 0x341, 0x751, 0x959, 0x169, 0x2C2, 0xACA, 0x8DA, 0x4E2,
2342  0xB0B, 0x713, 0x523, 0x12B, 0x284, 0x694, 0x89C, 0x0AC, 0x205, 0xA0D, 0x81D, 0x425},
2343  {0x448, 0x050, 0xA60, 0x668, 0x281, 0x091, 0x899, 0x6A9, 0x202, 0x40A, 0x81A, 0xA22,
2344  0x50B, 0x113, 0xB23, 0x72B, 0x344, 0x154, 0x95C, 0x76C, 0x2C5, 0x4CD, 0x8DD, 0xAE5},
2345  {0x048, 0xA50, 0x660, 0x468, 0x201, 0xA11, 0x819, 0x429, 0x342, 0x14A, 0x95A, 0x762,
2346  0x10B, 0xB13, 0x723, 0x52B, 0x2C4, 0xAD4, 0x8DC, 0x4EC, 0x285, 0x08D, 0x89D, 0x6A5},
2347  {0x808, 0xA10, 0x220, 0x428, 0x101, 0xB11, 0x719, 0x529, 0x142, 0x94A, 0x75A, 0x362,
2348  0x8CB, 0xAD3, 0x2E3, 0x4EB, 0x044, 0xA54, 0x65C, 0x46C, 0x085, 0x88D, 0x69D, 0x2A5},
2349  {0xA08, 0x210, 0x420, 0x828, 0x141, 0x351, 0x759, 0x969, 0x042, 0xA4A, 0x65A, 0x462,
2350  0xACB, 0x2D3, 0x4E3, 0x8EB, 0x084, 0x294, 0x69C, 0x8AC, 0x105, 0xB0D, 0x71D, 0x525},
2351  {0x408, 0x810, 0xA20, 0x228, 0x081, 0x891, 0x699, 0x2A9, 0x102, 0x50A, 0x71A, 0xB22,
2352  0x4CB, 0x8D3, 0xAE3, 0x2EB, 0x144, 0x954, 0x75C, 0x36C, 0x045, 0x44D, 0x65D, 0xA65},
2353 };
2354 
2355 // _axis_convert_num = {'X': 0, 'Y': 1, 'Z': 2, '-X': 3, '-Y': 4, '-Z': 5}
2356 
2357 BLI_INLINE int _axis_signed(const int axis)
2358 {
2359  return (axis < 3) ? axis : axis - 3;
2360 }
2361 
2363  int src_forward, int src_up, int dst_forward, int dst_up, float r_mat[3][3])
2364 {
2365  int value;
2366 
2367  if (src_forward == dst_forward && src_up == dst_up) {
2368  unit_m3(r_mat);
2369  return false;
2370  }
2371 
2372  if ((_axis_signed(src_forward) == _axis_signed(src_up)) ||
2373  (_axis_signed(dst_forward) == _axis_signed(dst_up))) {
2374  /* we could assert here! */
2375  unit_m3(r_mat);
2376  return false;
2377  }
2378 
2379  value = ((src_forward << (0 * 3)) | (src_up << (1 * 3)) | (dst_forward << (2 * 3)) |
2380  (dst_up << (3 * 3)));
2381 
2382  for (uint i = 0; i < (ARRAY_SIZE(_axis_convert_matrix)); i++) {
2383  for (uint j = 0; j < (ARRAY_SIZE(*_axis_convert_lut)); j++) {
2384  if (_axis_convert_lut[i][j] == value) {
2385  copy_m3_m3(r_mat, _axis_convert_matrix[i]);
2386  return true;
2387  }
2388  }
2389  }
2390  // BLI_assert(0);
2391  return false;
2392 }
2393 
2394 bool mat3_from_axis_conversion_single(int src_axis, int dst_axis, float r_mat[3][3])
2395 {
2396  if (src_axis == dst_axis) {
2397  unit_m3(r_mat);
2398  return false;
2399  }
2400 
2401  /* Pick predictable next axis. */
2402  int src_axis_next = (src_axis + 1) % 3;
2403  int dst_axis_next = (dst_axis + 1) % 3;
2404 
2405  if ((src_axis < 3) != (dst_axis < 3)) {
2406  /* Flip both axis so matrix sign remains positive. */
2407  dst_axis_next += 3;
2408  }
2409 
2410  return mat3_from_axis_conversion(src_axis, src_axis_next, dst_axis, dst_axis_next, r_mat);
2411 }
typedef float(TangentPoint)[2]
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_INLINE
MINLINE float saacos(float fac)
#define BLI_ASSERT_UNIT_EPSILON
#define M_SQRT2
Definition: BLI_math_base.h:29
#define BLI_ASSERT_UNIT_M3(m)
#define M_PI_2
Definition: BLI_math_base.h:23
MINLINE float square_f(float a)
#define BLI_ASSERT_UNIT_QUAT(q)
#define M_SQRT1_2
Definition: BLI_math_base.h:32
#define BLI_ASSERT_UNIT_V3(v)
#define M_PI
Definition: BLI_math_base.h:20
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:33
void orthogonalize_m4(float R[4][4], int axis)
Definition: math_matrix.c:1523
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:926
void mul_m4_fl(float R[4][4], float f)
Definition: math_matrix.c:967
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
void normalize_m3_m3(float R[3][3], const float M[3][3]) ATTR_NONNULL()
Definition: math_matrix.c:1927
void copy_m3_m3(float m1[3][3], const float m2[3][3])
Definition: math_matrix.c:71
void unit_m3(float m[3][3])
Definition: math_matrix.c:40
void add_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:1043
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:87
void mul_m3_fl(float R[3][3], float f)
Definition: math_matrix.c:956
void unit_m4(float m[4][4])
Definition: rct.c:1090
void copy_m4_m3(float m1[4][4], const float m2[3][3])
Definition: math_matrix.c:102
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
void normalize_m3(float R[3][3]) ATTR_NONNULL()
Definition: math_matrix.c:1912
bool is_orthonormal_m3(const float mat[3][3])
Definition: math_matrix.c:1809
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:729
#define mul_m4_series(...)
float determinant_m4(const float m[4][4])
Definition: math_matrix.c:2063
bool invert_m3_m3(float R[3][3], const float A[3][3])
Definition: math_matrix.c:1180
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:77
void mat4_to_size(float size[3], const float M[4][4])
Definition: math_matrix.c:2138
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
Definition: math_matrix.c:388
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3_v3(float r[3], const float a[3])
MINLINE bool is_zero_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
void ortho_v3_v3(float out[3], const float v[3])
Definition: math_vector.c:732
MINLINE void negate_v4_v4(float r[4], const float a[4])
MINLINE void negate_v3(float r[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE float len_squared_v4v4(const float a[4], const float b[4]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v3_length(float r[3], float unit_scale)
MINLINE void zero_v3(float r[3])
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
float angle_normalized_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:445
MINLINE void negate_v4(float r[4])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
Strict compiler flags for areas of code we want to ensure don't do conversions without us knowing abo...
unsigned int uint
Definition: BLI_sys_types.h:67
#define ARRAY_SIZE(arr)
#define UNLIKELY(x)
#define IN_RANGE_INCL(a, b, c)
#define LIKELY(x)
typedef double(DMatrix)[4][4]
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble z
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint order
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
#define sinf(x)
Definition: cuda/compat.h:102
#define cosf(x)
Definition: cuda/compat.h:101
#define tanf(x)
Definition: cuda/compat.h:104
SyclQueue void void size_t num_bytes void
int len
Definition: draw_manager.c:108
#define str(s)
uint nor
ccl_gpu_kernel_postfix ccl_global float int int int int sh
ccl_device_inline float2 fabs(const float2 &a)
Definition: math_float2.h:222
float angle_compat_rad(float angle, float angle_compat)
void rotation_between_quats_to_quat(float q[4], const float q1[4], const float q2[4])
void eulO_to_quat(float q[4], const float e[3], const short order)
float angle_qtqt(const float q1[4], const float q2[4])
void angle_to_mat2(float R[2][2], const float angle)
void mat3_normalized_to_eulO(float eul[3], const short order, const float m[3][3])
void mat4_to_compatible_eulO(float eul[3], const float oldrot[3], const short order, const float m[4][4])
void mat3_to_quat(float q[4], const float m[3][3])
static const RotOrderInfo * get_rotation_order_info(const short order)
float angle_signed_normalized_qtqt(const float q1[4], const float q2[4])
void rotation_between_vecs_to_quat(float q[4], const float v1[3], const float v2[3])
void print_qt(const char *str, const float q[4])
void vec_apply_track(float vec[3], short axis)
static void mat3_normalized_to_eulo2(const float mat[3][3], float eul1[3], float eul2[3], const short order)
float angle_normalized_qt(const float q[4])
float tri_to_quat(float q[4], const float a[3], const float b[3], const float c[3])
void mat3_normalized_to_compatible_eul(float eul[3], const float oldrot[3], float mat[3][3])
void quat_to_compatible_eulO(float eul[3], const float oldrot[3], const short order, const float quat[4])
void mat3_to_quat_is_ok(float q[4], const float wmat[3][3])
void add_eul_euleul(float r_eul[3], float a[3], float b[3], const short order)
float angle_signed_qt(const float q[4])
void invert_qt_normalized(float q[4])
void invert_qt_qt(float q1[4], const float q2[4])
void conjugate_qt_qt(float q1[4], const float q2[4])
Definition: math_rotation.c:77
void eul_to_mat3(float mat[3][3], const float eul[3])
static float mod_inline(float a, float b)
void add_weighted_dq_dq(DualQuat *dq_sum, const DualQuat *dq, float weight)
void eulO_to_axis_angle(float axis[3], float *angle, const float eul[3], const short order)
void mul_qt_fl(float q[4], const float f)
void quat_to_mat3(float m[3][3], const float q[4])
void mat3_to_eulO(float eul[3], const short order, const float m[3][3])
void axis_angle_normalized_to_mat3_ex(float mat[3][3], const float axis[3], const float angle_sin, const float angle_cos)
void axis_angle_to_mat3_single(float R[3][3], const char axis, const float angle)
void sub_qt_qtqt(float q[4], const float a[4], const float b[4])
void axis_angle_to_quat(float r[4], const float axis[3], const float angle)
void rotate_eulO(float beul[3], const short order, char axis, float ang)
float normalize_qt(float q[4])
void invert_qt(float q[4])
Definition: math_rotation.c:97
void quat_normalized_to_expmap(float expmap[3], const float q[4])
void quat_to_mat4(float m[4][4], const float q[4])
void dquat_to_mat4(float R[4][4], const DualQuat *dq)
void mat4_normalized_to_axis_angle(float axis[3], float *angle, const float mat[4][4])
void mat4_normalized_to_eulO(float eul[3], const short order, const float m[4][4])
void mul_qt_v3(const float q[4], float r[3])
Definition: math_rotation.c:59
void unit_qt(float q[4])
Definition: math_rotation.c:27
void mat3_normalized_to_compatible_eulO(float eul[3], const float oldrot[3], const short order, const float mat[3][3])
void quat_to_eulO(float e[3], short const order, const float q[4])
void axis_angle_normalized_to_mat3(float R[3][3], const float axis[3], const float angle)
void sub_eul_euleul(float r_eul[3], float a[3], float b[3], const short order)
void eul_to_quat(float quat[4], const float eul[3])
void mat4_to_eulO(float eul[3], const short order, const float m[4][4])
float fov_to_focallength(float hfov, float sensor)
void axis_angle_normalized_to_quat(float r[4], const float axis[3], const float angle)
void pow_qt_fl_normalized(float q[4], const float fac)
void mat4_to_axis_angle(float axis[3], float *angle, const float mat[4][4])
void mat4_normalized_to_eul(float eul[3], const float m[4][4])
float angle_signed_normalized_qt(const float q[4])
void quat_to_eul(float eul[3], const float quat[4])
float normalize_qt_qt(float r[4], const float q[4])
float dot_qtqt(const float a[4], const float b[4])
Definition: math_rotation.c:92
void invert_qt_qt_normalized(float q1[4], const float q2[4])
static void mat3_normalized_to_eul2(const float mat[3][3], float eul1[3], float eul2[3])
void sin_cos_from_fraction(int numerator, const int denominator, float *r_sin, float *r_cos)
bool is_zero_qt(const float q[4])
Definition: math_rotation.c:41
float quat_split_swing_and_twist(const float q_in[4], int axis, float r_swing[4], float r_twist[4])
void mat4_normalized_to_compatible_eulO(float eul[3], const float oldrot[3], const short order, const float m[4][4])
void mat3_normalized_to_eul(float eul[3], const float mat[3][3])
void mul_qt_qtqt(float q[4], const float a[4], const float b[4])
Definition: math_rotation.c:46
void axis_angle_to_quat_single(float q[4], const char axis, const float angle)
void quat_to_axis_angle(float axis[3], float *angle, const float q[4])
void mat3_to_eul(float eul[3], const float mat[3][3])
void quat_to_expmap(float expmap[3], const float q[4])
static float _axis_convert_matrix[23][3][3]
static void quat_to_mat3_no_error(float m[3][3], const float q[4])
void mat4_to_dquat(DualQuat *dq, const float basemat[4][4], const float mat[4][4])
void copy_dq_dq(DualQuat *r, const DualQuat *dq)
void mat3_to_compatible_eul(float eul[3], const float oldrot[3], float mat[3][3])
void axis_angle_to_eulO(float eul[3], const short order, const float axis[3], const float angle)
void mat4_to_quat(float q[4], const float m[4][4])
void rotation_between_vecs_to_mat3(float m[3][3], const float v1[3], const float v2[3])
bool mat3_from_axis_conversion(int src_forward, int src_up, int dst_forward, int dst_up, float r_mat[3][3])
float focallength_to_fov(float focal_length, float sensor)
static int _axis_convert_lut[23][24]
void axis_angle_to_mat3(float R[3][3], const float axis[3], const float angle)
void mul_v3m3_dq(float r[3], float R[3][3], DualQuat *dq)
void interp_qt_qtqt(float q[4], const float a[4], const float b[4], const float t)
void conjugate_qt(float q[4])
Definition: math_rotation.c:85
void compatible_eul(float eul[3], const float oldrot[3])
void quat_apply_track(float quat[4], short axis, short upflag)
void mat3_to_compatible_eulO(float eul[3], const float oldrot[3], const short order, const float mat[3][3])
void tri_to_quat_ex(float quat[4], const float v1[3], const float v2[3], const float v3[3], const float no_orig[3])
void eulO_to_mat4(float mat[4][4], const float e[3], const short order)
void axis_angle_to_mat4(float R[4][4], const float axis[3], const float angle)
void mat4_to_eul(float eul[3], const float m[4][4])
void quat_to_compatible_eul(float eul[3], const float oldrot[3], const float quat[4])
void mat4_normalized_to_quat(float q[4], const float m[4][4])
void axis_angle_to_mat4_single(float R[4][4], const char axis, const float angle)
float angle_wrap_deg(float angle)
void unit_axis_angle(float axis[3], float *angle)
Definition: math_rotation.c:19
void mat3_to_axis_angle(float axis[3], float *angle, const float mat[3][3])
struct RotOrderInfo RotOrderInfo
float angle_qt(const float q[4])
void copy_qt_qt(float q[4], const float a[4])
Definition: math_rotation.c:33
float angle_wrap_rad(float angle)
void normalize_dq(DualQuat *dq, float totweight)
void eulO_to_mat3(float M[3][3], const float e[3], const short order)
void quat_to_compatible_quat(float q[4], const float a[4], const float old[4])
void expmap_to_quat(float r[4], const float expmap[3])
BLI_INLINE int _axis_signed(const int axis)
void mat3_normalized_to_quat(float q[4], const float mat[3][3])
void interp_dot_slerp(const float t, const float cosom, float r_w[2])
float angle_signed_qtqt(const float q1[4], const float q2[4])
void rotate_eul(float beul[3], const char axis, const float ang)
static const RotOrderInfo rotOrders[]
void mat3_normalized_to_axis_angle(float axis[3], float *angle, const float mat[3][3])
float angle_normalized_qtqt(const float q1[4], const float q2[4])
void vec_to_quat(float q[4], const float vec[3], short axis, const short upflag)
void eul_to_mat4(float mat[4][4], const float eul[3])
void add_qt_qtqt(float q[4], const float a[4], const float b[4], const float t)
bool mat3_from_axis_conversion_single(int src_axis, int dst_axis, float r_mat[3][3])
void eulO_to_gimbal_axis(float gmat[3][3], const float eul[3], const short order)
#define M
#define R
#define atan2f(x, y)
Definition: metal/compat.h:227
#define atanf(x)
Definition: metal/compat.h:223
#define hypotf(x, y)
Definition: metal/compat.h:226
#define floorf(x)
Definition: metal/compat.h:224
#define acosf(x)
Definition: metal/compat.h:222
#define fabsf(x)
Definition: metal/compat.h:219
#define sqrtf(x)
Definition: metal/compat.h:243
static unsigned c
Definition: RandGen.cpp:83
static unsigned a[3]
Definition: RandGen.cpp:78
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
Definition: rall1d.h:319
INLINE Rall1d< T, V, S > acos(const Rall1d< T, V, S > &x)
Definition: rall1d.h:399
INLINE Rall1d< T, V, S > sin(const Rall1d< T, V, S > &arg)
Definition: rall1d.h:311
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
const btScalar eps
Definition: poly34.cpp:11
float scale_weight
Definition: DNA_vec_types.h:79
float scale[4][4]
Definition: DNA_vec_types.h:78
float quat[4]
Definition: DNA_vec_types.h:75
float trans[4]
Definition: DNA_vec_types.h:76