Blender  V2.93
math_geom.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  *
19  * The Original Code is: some of this file.
20  */
21 
26 #include "MEM_guardedalloc.h"
27 
28 #include "BLI_math.h"
29 #include "BLI_math_bits.h"
30 #include "BLI_utildefines.h"
31 
32 #include "BLI_strict_flags.h"
33 
34 /********************************** Polygons *********************************/
35 
36 void cross_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
37 {
38  float n1[3], n2[3];
39 
40  n1[0] = v1[0] - v2[0];
41  n2[0] = v2[0] - v3[0];
42  n1[1] = v1[1] - v2[1];
43  n2[1] = v2[1] - v3[1];
44  n1[2] = v1[2] - v2[2];
45  n2[2] = v2[2] - v3[2];
46  n[0] = n1[1] * n2[2] - n1[2] * n2[1];
47  n[1] = n1[2] * n2[0] - n1[0] * n2[2];
48  n[2] = n1[0] * n2[1] - n1[1] * n2[0];
49 }
50 
51 float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
52 {
53  float n1[3], n2[3];
54 
55  n1[0] = v1[0] - v2[0];
56  n2[0] = v2[0] - v3[0];
57  n1[1] = v1[1] - v2[1];
58  n2[1] = v2[1] - v3[1];
59  n1[2] = v1[2] - v2[2];
60  n2[2] = v2[2] - v3[2];
61  n[0] = n1[1] * n2[2] - n1[2] * n2[1];
62  n[1] = n1[2] * n2[0] - n1[0] * n2[2];
63  n[2] = n1[0] * n2[1] - n1[1] * n2[0];
64 
65  return normalize_v3(n);
66 }
67 
69  float n[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3])
70 {
71  /* real cross! */
72  float n1[3], n2[3];
73 
74  n1[0] = v1[0] - v3[0];
75  n1[1] = v1[1] - v3[1];
76  n1[2] = v1[2] - v3[2];
77 
78  n2[0] = v2[0] - v4[0];
79  n2[1] = v2[1] - v4[1];
80  n2[2] = v2[2] - v4[2];
81 
82  n[0] = n1[1] * n2[2] - n1[2] * n2[1];
83  n[1] = n1[2] * n2[0] - n1[0] * n2[2];
84  n[2] = n1[0] * n2[1] - n1[1] * n2[0];
85 
86  return normalize_v3(n);
87 }
88 
94 float normal_poly_v3(float n[3], const float verts[][3], unsigned int nr)
95 {
96  cross_poly_v3(n, verts, nr);
97  return normalize_v3(n);
98 }
99 
100 float area_quad_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
101 {
102  const float verts[4][3] = {{UNPACK3(v1)}, {UNPACK3(v2)}, {UNPACK3(v3)}, {UNPACK3(v4)}};
103  return area_poly_v3(verts, 4);
104 }
105 
106 float area_squared_quad_v3(const float v1[3],
107  const float v2[3],
108  const float v3[3],
109  const float v4[3])
110 {
111  const float verts[4][3] = {{UNPACK3(v1)}, {UNPACK3(v2)}, {UNPACK3(v3)}, {UNPACK3(v4)}};
112  return area_squared_poly_v3(verts, 4);
113 }
114 
115 /* Triangles */
116 float area_tri_v3(const float v1[3], const float v2[3], const float v3[3])
117 {
118  float n[3];
119  cross_tri_v3(n, v1, v2, v3);
120  return len_v3(n) * 0.5f;
121 }
122 
123 float area_squared_tri_v3(const float v1[3], const float v2[3], const float v3[3])
124 {
125  float n[3];
126  cross_tri_v3(n, v1, v2, v3);
127  mul_v3_fl(n, 0.5f);
128  return len_squared_v3(n);
129 }
130 
131 float area_tri_signed_v3(const float v1[3],
132  const float v2[3],
133  const float v3[3],
134  const float normal[3])
135 {
136  float area, n[3];
137 
138  cross_tri_v3(n, v1, v2, v3);
139  area = len_v3(n) * 0.5f;
140 
141  /* negate area for flipped triangles */
142  if (dot_v3v3(n, normal) < 0.0f) {
143  area = -area;
144  }
145 
146  return area;
147 }
148 
149 float area_poly_v3(const float verts[][3], unsigned int nr)
150 {
151  float n[3];
152  cross_poly_v3(n, verts, nr);
153  return len_v3(n) * 0.5f;
154 }
155 
156 float area_squared_poly_v3(const float verts[][3], unsigned int nr)
157 {
158  float n[3];
159 
160  cross_poly_v3(n, verts, nr);
161  mul_v3_fl(n, 0.5f);
162  return len_squared_v3(n);
163 }
164 
171 float cross_poly_v2(const float verts[][2], unsigned int nr)
172 {
173  unsigned int a;
174  float cross;
175  const float *co_curr, *co_prev;
176 
177  /* The Trapezium Area Rule */
178  co_prev = verts[nr - 1];
179  co_curr = verts[0];
180  cross = 0.0f;
181  for (a = 0; a < nr; a++) {
182  cross += (co_curr[0] - co_prev[0]) * (co_curr[1] + co_prev[1]);
183  co_prev = co_curr;
184  co_curr += 2;
185  }
186 
187  return cross;
188 }
189 
190 void cross_poly_v3(float n[3], const float verts[][3], unsigned int nr)
191 {
192  const float *v_prev = verts[nr - 1];
193  const float *v_curr = verts[0];
194  unsigned int i;
195 
196  zero_v3(n);
197 
198  /* Newell's Method */
199  for (i = 0; i < nr; v_prev = v_curr, v_curr = verts[++i]) {
200  add_newell_cross_v3_v3v3(n, v_prev, v_curr);
201  }
202 }
203 
204 float area_poly_v2(const float verts[][2], unsigned int nr)
205 {
206  return fabsf(0.5f * cross_poly_v2(verts, nr));
207 }
208 
209 float area_poly_signed_v2(const float verts[][2], unsigned int nr)
210 {
211  return (0.5f * cross_poly_v2(verts, nr));
212 }
213 
214 float area_squared_poly_v2(const float verts[][2], unsigned int nr)
215 {
216  float area = area_poly_signed_v2(verts, nr);
217  return area * area;
218 }
219 
220 float cotangent_tri_weight_v3(const float v1[3], const float v2[3], const float v3[3])
221 {
222  float a[3], b[3], c[3], c_len;
223 
224  sub_v3_v3v3(a, v2, v1);
225  sub_v3_v3v3(b, v3, v1);
226  cross_v3_v3v3(c, a, b);
227 
228  c_len = len_v3(c);
229 
230  if (c_len > FLT_EPSILON) {
231  return dot_v3v3(a, b) / c_len;
232  }
233 
234  return 0.0f;
235 }
236 
237 /********************************* Planes **********************************/
238 
243 void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
244 {
245  copy_v3_v3(r_plane, plane_no);
246  r_plane[3] = -dot_v3v3(r_plane, plane_co);
247 }
248 
252 void plane_to_point_vector_v3(const float plane[4], float r_plane_co[3], float r_plane_no[3])
253 {
254  mul_v3_v3fl(r_plane_co, plane, (-plane[3] / len_squared_v3(plane)));
255  copy_v3_v3(r_plane_no, plane);
256 }
257 
261 void plane_to_point_vector_v3_normalized(const float plane[4],
262  float r_plane_co[3],
263  float r_plane_no[3])
264 {
265  const float length = normalize_v3_v3(r_plane_no, plane);
266  mul_v3_v3fl(r_plane_co, r_plane_no, (-plane[3] / length));
267 }
268 
269 /********************************* Volume **********************************/
270 
274 float volume_tetrahedron_v3(const float v1[3],
275  const float v2[3],
276  const float v3[3],
277  const float v4[3])
278 {
279  float m[3][3];
280  sub_v3_v3v3(m[0], v1, v2);
281  sub_v3_v3v3(m[1], v2, v3);
282  sub_v3_v3v3(m[2], v3, v4);
283  return fabsf(determinant_m3_array(m)) / 6.0f;
284 }
285 
289 float volume_tetrahedron_signed_v3(const float v1[3],
290  const float v2[3],
291  const float v3[3],
292  const float v4[3])
293 {
294  float m[3][3];
295  sub_v3_v3v3(m[0], v1, v2);
296  sub_v3_v3v3(m[1], v2, v3);
297  sub_v3_v3v3(m[2], v3, v4);
298  return determinant_m3_array(m) / 6.0f;
299 }
300 
307 float volume_tri_tetrahedron_signed_v3_6x(const float v1[3], const float v2[3], const float v3[3])
308 {
309  float v_cross[3];
310  cross_v3_v3v3(v_cross, v1, v2);
311  float tetra_volume = dot_v3v3(v_cross, v3);
312  return tetra_volume;
313 }
314 
315 float volume_tri_tetrahedron_signed_v3(const float v1[3], const float v2[3], const float v3[3])
316 {
317  return volume_tri_tetrahedron_signed_v3_6x(v1, v2, v3) / 6.0f;
318 }
319 
320 /********************************* Distance **********************************/
321 
322 /* distance p to line v1-v2
323  * using Hesse formula, NO LINE PIECE! */
324 float dist_squared_to_line_v2(const float p[2], const float l1[2], const float l2[2])
325 {
326  float closest[2];
327 
328  closest_to_line_v2(closest, p, l1, l2);
329 
330  return len_squared_v2v2(closest, p);
331 }
332 float dist_to_line_v2(const float p[2], const float l1[2], const float l2[2])
333 {
334  return sqrtf(dist_squared_to_line_v2(p, l1, l2));
335 }
336 
337 /* distance p to line-piece v1-v2 */
338 float dist_squared_to_line_segment_v2(const float p[2], const float l1[2], const float l2[2])
339 {
340  float closest[2];
341 
343 
344  return len_squared_v2v2(closest, p);
345 }
346 
347 float dist_to_line_segment_v2(const float p[2], const float l1[2], const float l2[2])
348 {
349  return sqrtf(dist_squared_to_line_segment_v2(p, l1, l2));
350 }
351 
352 /* point closest to v1 on line v2-v3 in 2D */
353 void closest_to_line_segment_v2(float r_close[2],
354  const float p[2],
355  const float l1[2],
356  const float l2[2])
357 {
358  float lambda, cp[2];
359 
360  lambda = closest_to_line_v2(cp, p, l1, l2);
361 
362  /* flip checks for !finite case (when segment is a point) */
363  if (!(lambda > 0.0f)) {
364  copy_v2_v2(r_close, l1);
365  }
366  else if (!(lambda < 1.0f)) {
367  copy_v2_v2(r_close, l2);
368  }
369  else {
370  copy_v2_v2(r_close, cp);
371  }
372 }
373 
374 /* point closest to v1 on line v2-v3 in 3D */
375 void closest_to_line_segment_v3(float r_close[3],
376  const float p[3],
377  const float l1[3],
378  const float l2[3])
379 {
380  float lambda, cp[3];
381 
382  lambda = closest_to_line_v3(cp, p, l1, l2);
383 
384  /* flip checks for !finite case (when segment is a point) */
385  if (!(lambda > 0.0f)) {
386  copy_v3_v3(r_close, l1);
387  }
388  else if (!(lambda < 1.0f)) {
389  copy_v3_v3(r_close, l2);
390  }
391  else {
392  copy_v3_v3(r_close, cp);
393  }
394 }
395 
405 void closest_to_plane_v3(float r_close[3], const float plane[4], const float pt[3])
406 {
407  const float len_sq = len_squared_v3(plane);
408  const float side = plane_point_side_v3(plane, pt);
409  madd_v3_v3v3fl(r_close, pt, plane, -side / len_sq);
410 }
411 
412 void closest_to_plane_normalized_v3(float r_close[3], const float plane[4], const float pt[3])
413 {
414  const float side = plane_point_side_v3(plane, pt);
415  BLI_ASSERT_UNIT_V3(plane);
416  madd_v3_v3v3fl(r_close, pt, plane, -side);
417 }
418 
419 void closest_to_plane3_v3(float r_close[3], const float plane[3], const float pt[3])
420 {
421  const float len_sq = len_squared_v3(plane);
422  const float side = dot_v3v3(plane, pt);
423  madd_v3_v3v3fl(r_close, pt, plane, -side / len_sq);
424 }
425 
426 void closest_to_plane3_normalized_v3(float r_close[3], const float plane[3], const float pt[3])
427 {
428  const float side = dot_v3v3(plane, pt);
429  BLI_ASSERT_UNIT_V3(plane);
430  madd_v3_v3v3fl(r_close, pt, plane, -side);
431 }
432 
433 float dist_signed_squared_to_plane_v3(const float pt[3], const float plane[4])
434 {
435  const float len_sq = len_squared_v3(plane);
436  const float side = plane_point_side_v3(plane, pt);
437  const float fac = side / len_sq;
438  return copysignf(len_sq * (fac * fac), side);
439 }
440 float dist_squared_to_plane_v3(const float pt[3], const float plane[4])
441 {
442  const float len_sq = len_squared_v3(plane);
443  const float side = plane_point_side_v3(plane, pt);
444  const float fac = side / len_sq;
445  /* only difference to code above - no 'copysignf' */
446  return len_sq * (fac * fac);
447 }
448 
449 float dist_signed_squared_to_plane3_v3(const float pt[3], const float plane[3])
450 {
451  const float len_sq = len_squared_v3(plane);
452  const float side = dot_v3v3(plane, pt); /* only difference with 'plane[4]' version */
453  const float fac = side / len_sq;
454  return copysignf(len_sq * (fac * fac), side);
455 }
456 float dist_squared_to_plane3_v3(const float pt[3], const float plane[3])
457 {
458  const float len_sq = len_squared_v3(plane);
459  const float side = dot_v3v3(plane, pt); /* only difference with 'plane[4]' version */
460  const float fac = side / len_sq;
461  /* only difference to code above - no 'copysignf' */
462  return len_sq * (fac * fac);
463 }
464 
468 float dist_signed_to_plane_v3(const float pt[3], const float plane[4])
469 {
470  const float len_sq = len_squared_v3(plane);
471  const float side = plane_point_side_v3(plane, pt);
472  const float fac = side / len_sq;
473  return sqrtf(len_sq) * fac;
474 }
475 float dist_to_plane_v3(const float pt[3], const float plane[4])
476 {
477  return fabsf(dist_signed_to_plane_v3(pt, plane));
478 }
479 
480 float dist_signed_to_plane3_v3(const float pt[3], const float plane[3])
481 {
482  const float len_sq = len_squared_v3(plane);
483  const float side = dot_v3v3(plane, pt); /* only difference with 'plane[4]' version */
484  const float fac = side / len_sq;
485  return sqrtf(len_sq) * fac;
486 }
487 float dist_to_plane3_v3(const float pt[3], const float plane[3])
488 {
489  return fabsf(dist_signed_to_plane3_v3(pt, plane));
490 }
491 
492 /* distance v1 to line-piece l1-l2 in 3D */
493 float dist_squared_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3])
494 {
495  float closest[3];
496 
498 
499  return len_squared_v3v3(closest, p);
500 }
501 
502 float dist_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3])
503 {
504  return sqrtf(dist_squared_to_line_segment_v3(p, l1, l2));
505 }
506 
507 float dist_squared_to_line_v3(const float p[3], const float l1[3], const float l2[3])
508 {
509  float closest[3];
510 
511  closest_to_line_v3(closest, p, l1, l2);
512 
513  return len_squared_v3v3(closest, p);
514 }
515 float dist_to_line_v3(const float p[3], const float l1[3], const float l2[3])
516 {
517  return sqrtf(dist_squared_to_line_v3(p, l1, l2));
518 }
519 
544  const float v1[3],
545  const float v2[3],
546  const float v3[3],
547  const float axis_ref[3])
548 {
549  float dir_a[3], dir_b[3];
550  float plane_a[3], plane_b[3];
551  float dist_a, dist_b;
552  float axis[3];
553  float s_p_v2[3];
554  bool flip = false;
555 
556  sub_v3_v3v3(dir_a, v1, v2);
557  sub_v3_v3v3(dir_b, v3, v2);
558 
559  cross_v3_v3v3(axis, dir_a, dir_b);
560 
561  if ((len_squared_v3(axis) < FLT_EPSILON)) {
562  copy_v3_v3(axis, axis_ref);
563  }
564  else if (dot_v3v3(axis, axis_ref) < 0.0f) {
565  /* concave */
566  flip = true;
567  negate_v3(axis);
568  }
569 
570  cross_v3_v3v3(plane_a, dir_a, axis);
571  cross_v3_v3v3(plane_b, axis, dir_b);
572 
573 #if 0
574  plane_from_point_normal_v3(plane_a, v2, plane_a);
575  plane_from_point_normal_v3(plane_b, v2, plane_b);
576 
577  dist_a = dist_signed_squared_to_plane_v3(p, plane_a);
578  dist_b = dist_signed_squared_to_plane_v3(p, plane_b);
579 #else
580  /* calculate without the planes 4th component to avoid float precision issues */
581  sub_v3_v3v3(s_p_v2, p, v2);
582 
583  dist_a = dist_signed_squared_to_plane3_v3(s_p_v2, plane_a);
584  dist_b = dist_signed_squared_to_plane3_v3(s_p_v2, plane_b);
585 #endif
586 
587  if (flip) {
588  return min_ff(dist_a, dist_b);
589  }
590 
591  return max_ff(dist_a, dist_b);
592 }
593 
600 float dist_squared_to_ray_v3_normalized(const float ray_origin[3],
601  const float ray_direction[3],
602  const float co[3])
603 {
604  float origin_to_co[3];
605  sub_v3_v3v3(origin_to_co, co, ray_origin);
606 
607  float origin_to_proj[3];
608  project_v3_v3v3_normalized(origin_to_proj, origin_to_co, ray_direction);
609 
610  float co_projected_on_ray[3];
611  add_v3_v3v3(co_projected_on_ray, ray_origin, origin_to_proj);
612 
613  return len_squared_v3v3(co, co_projected_on_ray);
614 }
615 
622 float dist_squared_ray_to_seg_v3(const float ray_origin[3],
623  const float ray_direction[3],
624  const float v0[3],
625  const float v1[3],
626  float r_point[3],
627  float *r_depth)
628 {
629  float lambda, depth;
630  if (isect_ray_line_v3(ray_origin, ray_direction, v0, v1, &lambda)) {
631  if (lambda <= 0.0f) {
632  copy_v3_v3(r_point, v0);
633  }
634  else if (lambda >= 1.0f) {
635  copy_v3_v3(r_point, v1);
636  }
637  else {
638  interp_v3_v3v3(r_point, v0, v1, lambda);
639  }
640  }
641  else {
642  /* has no nearest point, only distance squared. */
643  /* Calculate the distance to the point v0 then */
644  copy_v3_v3(r_point, v0);
645  }
646 
647  float dvec[3];
648  sub_v3_v3v3(dvec, r_point, ray_origin);
649  depth = dot_v3v3(dvec, ray_direction);
650 
651  if (r_depth) {
652  *r_depth = depth;
653  }
654 
655  return len_squared_v3(dvec) - square_f(depth);
656 }
657 
658 /* Returns the coordinates of the nearest vertex and
659  * the farthest vertex from a plane (or normal). */
660 void aabb_get_near_far_from_plane(const float plane_no[3],
661  const float bbmin[3],
662  const float bbmax[3],
663  float bb_near[3],
664  float bb_afar[3])
665 {
666  if (plane_no[0] < 0.0f) {
667  bb_near[0] = bbmax[0];
668  bb_afar[0] = bbmin[0];
669  }
670  else {
671  bb_near[0] = bbmin[0];
672  bb_afar[0] = bbmax[0];
673  }
674  if (plane_no[1] < 0.0f) {
675  bb_near[1] = bbmax[1];
676  bb_afar[1] = bbmin[1];
677  }
678  else {
679  bb_near[1] = bbmin[1];
680  bb_afar[1] = bbmax[1];
681  }
682  if (plane_no[2] < 0.0f) {
683  bb_near[2] = bbmax[2];
684  bb_afar[2] = bbmin[2];
685  }
686  else {
687  bb_near[2] = bbmin[2];
688  bb_afar[2] = bbmax[2];
689  }
690 }
691 
692 /* -------------------------------------------------------------------- */
697  const float ray_origin[3],
698  const float ray_direction[3])
699 {
700  copy_v3_v3(neasrest_precalc->ray_origin, ray_origin);
701  copy_v3_v3(neasrest_precalc->ray_direction, ray_direction);
702 
703  for (int i = 0; i < 3; i++) {
704  neasrest_precalc->ray_inv_dir[i] = (neasrest_precalc->ray_direction[i] != 0.0f) ?
705  (1.0f / neasrest_precalc->ray_direction[i]) :
706  FLT_MAX;
707  }
708 }
709 
714  const float bb_min[3],
715  const float bb_max[3],
716  float r_point[3],
717  float *r_depth)
718 {
719  // bool r_axis_closest[3];
720  float local_bvmin[3], local_bvmax[3];
721  aabb_get_near_far_from_plane(data->ray_direction, bb_min, bb_max, local_bvmin, local_bvmax);
722 
723  const float tmin[3] = {
724  (local_bvmin[0] - data->ray_origin[0]) * data->ray_inv_dir[0],
725  (local_bvmin[1] - data->ray_origin[1]) * data->ray_inv_dir[1],
726  (local_bvmin[2] - data->ray_origin[2]) * data->ray_inv_dir[2],
727  };
728  const float tmax[3] = {
729  (local_bvmax[0] - data->ray_origin[0]) * data->ray_inv_dir[0],
730  (local_bvmax[1] - data->ray_origin[1]) * data->ray_inv_dir[1],
731  (local_bvmax[2] - data->ray_origin[2]) * data->ray_inv_dir[2],
732  };
733  /* `va` and `vb` are the coordinates of the AABB edge closest to the ray */
734  float va[3], vb[3];
735  /* `rtmin` and `rtmax` are the minimum and maximum distances of the ray hits on the AABB */
736  float rtmin, rtmax;
737  int main_axis;
738 
739  if ((tmax[0] <= tmax[1]) && (tmax[0] <= tmax[2])) {
740  rtmax = tmax[0];
741  va[0] = vb[0] = local_bvmax[0];
742  main_axis = 3;
743  // r_axis_closest[0] = neasrest_precalc->ray_direction[0] < 0.0f;
744  }
745  else if ((tmax[1] <= tmax[0]) && (tmax[1] <= tmax[2])) {
746  rtmax = tmax[1];
747  va[1] = vb[1] = local_bvmax[1];
748  main_axis = 2;
749  // r_axis_closest[1] = neasrest_precalc->ray_direction[1] < 0.0f;
750  }
751  else {
752  rtmax = tmax[2];
753  va[2] = vb[2] = local_bvmax[2];
754  main_axis = 1;
755  // r_axis_closest[2] = neasrest_precalc->ray_direction[2] < 0.0f;
756  }
757 
758  if ((tmin[0] >= tmin[1]) && (tmin[0] >= tmin[2])) {
759  rtmin = tmin[0];
760  va[0] = vb[0] = local_bvmin[0];
761  main_axis -= 3;
762  // r_axis_closest[0] = neasrest_precalc->ray_direction[0] >= 0.0f;
763  }
764  else if ((tmin[1] >= tmin[0]) && (tmin[1] >= tmin[2])) {
765  rtmin = tmin[1];
766  va[1] = vb[1] = local_bvmin[1];
767  main_axis -= 1;
768  // r_axis_closest[1] = neasrest_precalc->ray_direction[1] >= 0.0f;
769  }
770  else {
771  rtmin = tmin[2];
772  va[2] = vb[2] = local_bvmin[2];
773  main_axis -= 2;
774  // r_axis_closest[2] = neasrest_precalc->ray_direction[2] >= 0.0f;
775  }
776  if (main_axis < 0) {
777  main_axis += 3;
778  }
779 
780  /* if rtmin <= rtmax, ray intersect `AABB` */
781  if (rtmin <= rtmax) {
782  float dvec[3];
783  copy_v3_v3(r_point, local_bvmax);
784  sub_v3_v3v3(dvec, local_bvmax, data->ray_origin);
785  *r_depth = dot_v3v3(dvec, data->ray_direction);
786  return 0.0f;
787  }
788 
789  if (data->ray_direction[main_axis] >= 0.0f) {
790  va[main_axis] = local_bvmin[main_axis];
791  vb[main_axis] = local_bvmax[main_axis];
792  }
793  else {
794  va[main_axis] = local_bvmax[main_axis];
795  vb[main_axis] = local_bvmin[main_axis];
796  }
797 
799  data->ray_origin, data->ray_direction, va, vb, r_point, r_depth);
800 }
801 
802 float dist_squared_ray_to_aabb_v3_simple(const float ray_origin[3],
803  const float ray_direction[3],
804  const float bb_min[3],
805  const float bb_max[3],
806  float r_point[3],
807  float *r_depth)
808 {
809  struct DistRayAABB_Precalc data;
811  return dist_squared_ray_to_aabb_v3(&data, bb_min, bb_max, r_point, r_depth);
812 }
815 /* -------------------------------------------------------------------- */
824  const float projmat[4][4],
825  const float winsize[2],
826  const float mval[2])
827 {
828  float win_half[2], relative_mval[2], px[4], py[4];
829 
830  mul_v2_v2fl(win_half, winsize, 0.5f);
831  sub_v2_v2v2(precalc->mval, mval, win_half);
832 
833  relative_mval[0] = precalc->mval[0] / win_half[0];
834  relative_mval[1] = precalc->mval[1] / win_half[1];
835 
836  copy_m4_m4(precalc->pmat, projmat);
837  for (int i = 0; i < 4; i++) {
838  px[i] = precalc->pmat[i][0] - precalc->pmat[i][3] * relative_mval[0];
839  py[i] = precalc->pmat[i][1] - precalc->pmat[i][3] * relative_mval[1];
840 
841  precalc->pmat[i][0] *= win_half[0];
842  precalc->pmat[i][1] *= win_half[1];
843  }
844 #if 0
845  float projmat_trans[4][4];
846  transpose_m4_m4(projmat_trans, projmat);
848  projmat_trans[0], projmat_trans[1], projmat_trans[3], precalc->ray_origin)) {
849  /* Orthographic projection. */
850  isect_plane_plane_v3(px, py, precalc->ray_origin, precalc->ray_direction);
851  }
852  else {
853  /* Perspective projection. */
854  cross_v3_v3v3(precalc->ray_direction, py, px);
855  //normalize_v3(precalc->ray_direction);
856  }
857 #else
858  if (!isect_plane_plane_v3(px, py, precalc->ray_origin, precalc->ray_direction)) {
859  /* Matrix with weird coplanar planes. Undetermined origin.*/
860  zero_v3(precalc->ray_origin);
861  precalc->ray_direction[0] = precalc->pmat[0][3];
862  precalc->ray_direction[1] = precalc->pmat[1][3];
863  precalc->ray_direction[2] = precalc->pmat[2][3];
864  }
865 #endif
866 
867  for (int i = 0; i < 3; i++) {
868  precalc->ray_inv_dir[i] = (precalc->ray_direction[i] != 0.0f) ?
869  (1.0f / precalc->ray_direction[i]) :
870  FLT_MAX;
871  }
872 }
873 
874 /* Returns the distance from a 2d coordinate to a BoundBox (Projected) */
876  const float bbmin[3],
877  const float bbmax[3],
878  bool r_axis_closest[3])
879 {
880  float local_bvmin[3], local_bvmax[3];
881  aabb_get_near_far_from_plane(data->ray_direction, bbmin, bbmax, local_bvmin, local_bvmax);
882 
883  const float tmin[3] = {
884  (local_bvmin[0] - data->ray_origin[0]) * data->ray_inv_dir[0],
885  (local_bvmin[1] - data->ray_origin[1]) * data->ray_inv_dir[1],
886  (local_bvmin[2] - data->ray_origin[2]) * data->ray_inv_dir[2],
887  };
888  const float tmax[3] = {
889  (local_bvmax[0] - data->ray_origin[0]) * data->ray_inv_dir[0],
890  (local_bvmax[1] - data->ray_origin[1]) * data->ray_inv_dir[1],
891  (local_bvmax[2] - data->ray_origin[2]) * data->ray_inv_dir[2],
892  };
893  /* `va` and `vb` are the coordinates of the AABB edge closest to the ray */
894  float va[3], vb[3];
895  /* `rtmin` and `rtmax` are the minimum and maximum distances of the ray hits on the AABB */
896  float rtmin, rtmax;
897  int main_axis;
898 
899  r_axis_closest[0] = false;
900  r_axis_closest[1] = false;
901  r_axis_closest[2] = false;
902 
903  if ((tmax[0] <= tmax[1]) && (tmax[0] <= tmax[2])) {
904  rtmax = tmax[0];
905  va[0] = vb[0] = local_bvmax[0];
906  main_axis = 3;
907  r_axis_closest[0] = data->ray_direction[0] < 0.0f;
908  }
909  else if ((tmax[1] <= tmax[0]) && (tmax[1] <= tmax[2])) {
910  rtmax = tmax[1];
911  va[1] = vb[1] = local_bvmax[1];
912  main_axis = 2;
913  r_axis_closest[1] = data->ray_direction[1] < 0.0f;
914  }
915  else {
916  rtmax = tmax[2];
917  va[2] = vb[2] = local_bvmax[2];
918  main_axis = 1;
919  r_axis_closest[2] = data->ray_direction[2] < 0.0f;
920  }
921 
922  if ((tmin[0] >= tmin[1]) && (tmin[0] >= tmin[2])) {
923  rtmin = tmin[0];
924  va[0] = vb[0] = local_bvmin[0];
925  main_axis -= 3;
926  r_axis_closest[0] = data->ray_direction[0] >= 0.0f;
927  }
928  else if ((tmin[1] >= tmin[0]) && (tmin[1] >= tmin[2])) {
929  rtmin = tmin[1];
930  va[1] = vb[1] = local_bvmin[1];
931  main_axis -= 1;
932  r_axis_closest[1] = data->ray_direction[1] >= 0.0f;
933  }
934  else {
935  rtmin = tmin[2];
936  va[2] = vb[2] = local_bvmin[2];
937  main_axis -= 2;
938  r_axis_closest[2] = data->ray_direction[2] >= 0.0f;
939  }
940  if (main_axis < 0) {
941  main_axis += 3;
942  }
943 
944  /* if rtmin <= rtmax, ray intersect `AABB` */
945  if (rtmin <= rtmax) {
946  return 0;
947  }
948 
949  if (data->ray_direction[main_axis] >= 0.0f) {
950  va[main_axis] = local_bvmin[main_axis];
951  vb[main_axis] = local_bvmax[main_axis];
952  }
953  else {
954  va[main_axis] = local_bvmax[main_axis];
955  vb[main_axis] = local_bvmin[main_axis];
956  }
957  float scale = fabsf(local_bvmax[main_axis] - local_bvmin[main_axis]);
958 
959  float va2d[2] = {
960  (dot_m4_v3_row_x(data->pmat, va) + data->pmat[3][0]),
961  (dot_m4_v3_row_y(data->pmat, va) + data->pmat[3][1]),
962  };
963  float vb2d[2] = {
964  (va2d[0] + data->pmat[main_axis][0] * scale),
965  (va2d[1] + data->pmat[main_axis][1] * scale),
966  };
967 
968  float w_a = mul_project_m4_v3_zfac(data->pmat, va);
969  if (w_a != 1.0f) {
970  /* Perspective Projection. */
971  float w_b = w_a + data->pmat[main_axis][3] * scale;
972  va2d[0] /= w_a;
973  va2d[1] /= w_a;
974  vb2d[0] /= w_b;
975  vb2d[1] /= w_b;
976  }
977 
978  float dvec[2], edge[2], lambda, rdist_sq;
979  sub_v2_v2v2(dvec, data->mval, va2d);
980  sub_v2_v2v2(edge, vb2d, va2d);
981  lambda = dot_v2v2(dvec, edge);
982  if (lambda != 0.0f) {
983  lambda /= len_squared_v2(edge);
984  if (lambda <= 0.0f) {
985  rdist_sq = len_squared_v2v2(data->mval, va2d);
986  r_axis_closest[main_axis] = true;
987  }
988  else if (lambda >= 1.0f) {
989  rdist_sq = len_squared_v2v2(data->mval, vb2d);
990  r_axis_closest[main_axis] = false;
991  }
992  else {
993  madd_v2_v2fl(va2d, edge, lambda);
994  rdist_sq = len_squared_v2v2(data->mval, va2d);
995  r_axis_closest[main_axis] = lambda < 0.5f;
996  }
997  }
998  else {
999  rdist_sq = len_squared_v2v2(data->mval, va2d);
1000  }
1001 
1002  return rdist_sq;
1003 }
1004 
1005 float dist_squared_to_projected_aabb_simple(const float projmat[4][4],
1006  const float winsize[2],
1007  const float mval[2],
1008  const float bbmin[3],
1009  const float bbmax[3])
1010 {
1012  dist_squared_to_projected_aabb_precalc(&data, projmat, winsize, mval);
1013 
1014  bool dummy[3] = {true, true, true};
1015  return dist_squared_to_projected_aabb(&data, bbmin, bbmax, dummy);
1016 }
1019 /* Adapted from "Real-Time Collision Detection" by Christer Ericson,
1020  * published by Morgan Kaufmann Publishers, copyright 2005 Elsevier Inc.
1021  *
1022  * Set 'r' to the point in triangle (a, b, c) closest to point 'p' */
1024  float r[3], const float p[3], const float v1[3], const float v2[3], const float v3[3])
1025 {
1026  float ab[3], ac[3], ap[3], d1, d2;
1027  float bp[3], d3, d4, vc, cp[3], d5, d6, vb, va;
1028  float denom, v, w;
1029 
1030  /* Check if P in vertex region outside A */
1031  sub_v3_v3v3(ab, v2, v1);
1032  sub_v3_v3v3(ac, v3, v1);
1033  sub_v3_v3v3(ap, p, v1);
1034  d1 = dot_v3v3(ab, ap);
1035  d2 = dot_v3v3(ac, ap);
1036  if (d1 <= 0.0f && d2 <= 0.0f) {
1037  /* barycentric coordinates (1,0,0) */
1038  copy_v3_v3(r, v1);
1039  return;
1040  }
1041 
1042  /* Check if P in vertex region outside B */
1043  sub_v3_v3v3(bp, p, v2);
1044  d3 = dot_v3v3(ab, bp);
1045  d4 = dot_v3v3(ac, bp);
1046  if (d3 >= 0.0f && d4 <= d3) {
1047  /* barycentric coordinates (0,1,0) */
1048  copy_v3_v3(r, v2);
1049  return;
1050  }
1051  /* Check if P in edge region of AB, if so return projection of P onto AB */
1052  vc = d1 * d4 - d3 * d2;
1053  if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) {
1054  v = d1 / (d1 - d3);
1055  /* barycentric coordinates (1-v,v,0) */
1056  madd_v3_v3v3fl(r, v1, ab, v);
1057  return;
1058  }
1059  /* Check if P in vertex region outside C */
1060  sub_v3_v3v3(cp, p, v3);
1061  d5 = dot_v3v3(ab, cp);
1062  d6 = dot_v3v3(ac, cp);
1063  if (d6 >= 0.0f && d5 <= d6) {
1064  /* barycentric coordinates (0,0,1) */
1065  copy_v3_v3(r, v3);
1066  return;
1067  }
1068  /* Check if P in edge region of AC, if so return projection of P onto AC */
1069  vb = d5 * d2 - d1 * d6;
1070  if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) {
1071  w = d2 / (d2 - d6);
1072  /* barycentric coordinates (1-w,0,w) */
1073  madd_v3_v3v3fl(r, v1, ac, w);
1074  return;
1075  }
1076  /* Check if P in edge region of BC, if so return projection of P onto BC */
1077  va = d3 * d6 - d5 * d4;
1078  if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f) {
1079  w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
1080  /* barycentric coordinates (0,1-w,w) */
1081  sub_v3_v3v3(r, v3, v2);
1082  mul_v3_fl(r, w);
1083  add_v3_v3(r, v2);
1084  return;
1085  }
1086 
1087  /* P inside face region. Compute Q through its barycentric coordinates (u,v,w) */
1088  denom = 1.0f / (va + vb + vc);
1089  v = vb * denom;
1090  w = vc * denom;
1091 
1092  /* = u*a + v*b + w*c, u = va * denom = 1.0f - v - w */
1093  /* ac * w */
1094  mul_v3_fl(ac, w);
1095  /* a + ab * v */
1096  madd_v3_v3v3fl(r, v1, ab, v);
1097  /* a + ab * v + ac * w */
1098  add_v3_v3(r, ac);
1099 }
1100 
1101 /******************************* Intersection ********************************/
1102 
1103 /* intersect Line-Line, shorts */
1104 int isect_seg_seg_v2_int(const int v1[2], const int v2[2], const int v3[2], const int v4[2])
1105 {
1106  float div, lambda, mu;
1107 
1108  div = (float)((v2[0] - v1[0]) * (v4[1] - v3[1]) - (v2[1] - v1[1]) * (v4[0] - v3[0]));
1109  if (div == 0.0f) {
1110  return ISECT_LINE_LINE_COLINEAR;
1111  }
1112 
1113  lambda = (float)((v1[1] - v3[1]) * (v4[0] - v3[0]) - (v1[0] - v3[0]) * (v4[1] - v3[1])) / div;
1114 
1115  mu = (float)((v1[1] - v3[1]) * (v2[0] - v1[0]) - (v1[0] - v3[0]) * (v2[1] - v1[1])) / div;
1116 
1117  if (lambda >= 0.0f && lambda <= 1.0f && mu >= 0.0f && mu <= 1.0f) {
1118  if (lambda == 0.0f || lambda == 1.0f || mu == 0.0f || mu == 1.0f) {
1119  return ISECT_LINE_LINE_EXACT;
1120  }
1121  return ISECT_LINE_LINE_CROSS;
1122  }
1123  return ISECT_LINE_LINE_NONE;
1124 }
1125 
1126 /* intersect Line-Line, floats - gives intersection point */
1128  const float v0[2], const float v1[2], const float v2[2], const float v3[2], float r_vi[2])
1129 {
1130  float s10[2], s32[2];
1131  float div;
1132 
1133  sub_v2_v2v2(s10, v1, v0);
1134  sub_v2_v2v2(s32, v3, v2);
1135 
1136  div = cross_v2v2(s10, s32);
1137  if (div != 0.0f) {
1138  const float u = cross_v2v2(v1, v0);
1139  const float v = cross_v2v2(v3, v2);
1140 
1141  r_vi[0] = ((s32[0] * u) - (s10[0] * v)) / div;
1142  r_vi[1] = ((s32[1] * u) - (s10[1] * v)) / div;
1143 
1144  return ISECT_LINE_LINE_CROSS;
1145  }
1146 
1147  return ISECT_LINE_LINE_COLINEAR;
1148 }
1149 
1150 /* intersect Line-Line, floats */
1151 int isect_seg_seg_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2])
1152 {
1153  float div, lambda, mu;
1154 
1155  div = (v2[0] - v1[0]) * (v4[1] - v3[1]) - (v2[1] - v1[1]) * (v4[0] - v3[0]);
1156  if (div == 0.0f) {
1157  return ISECT_LINE_LINE_COLINEAR;
1158  }
1159 
1160  lambda = ((float)(v1[1] - v3[1]) * (v4[0] - v3[0]) - (v1[0] - v3[0]) * (v4[1] - v3[1])) / div;
1161 
1162  mu = ((float)(v1[1] - v3[1]) * (v2[0] - v1[0]) - (v1[0] - v3[0]) * (v2[1] - v1[1])) / div;
1163 
1164  if (lambda >= 0.0f && lambda <= 1.0f && mu >= 0.0f && mu <= 1.0f) {
1165  if (lambda == 0.0f || lambda == 1.0f || mu == 0.0f || mu == 1.0f) {
1166  return ISECT_LINE_LINE_EXACT;
1167  }
1168  return ISECT_LINE_LINE_CROSS;
1169  }
1170  return ISECT_LINE_LINE_NONE;
1171 }
1172 
1173 /* Returns a point on each segment that is closest to the other. */
1174 void isect_seg_seg_v3(const float a0[3],
1175  const float a1[3],
1176  const float b0[3],
1177  const float b1[3],
1178  float r_a[3],
1179  float r_b[3])
1180 {
1181  float fac_a, fac_b;
1182  float a_dir[3], b_dir[3], a0b0[3], crs_ab[3];
1183  sub_v3_v3v3(a_dir, a1, a0);
1184  sub_v3_v3v3(b_dir, b1, b0);
1185  sub_v3_v3v3(a0b0, b0, a0);
1186  cross_v3_v3v3(crs_ab, b_dir, a_dir);
1187  const float nlen = len_squared_v3(crs_ab);
1188 
1189  if (nlen == 0.0f) {
1190  /* Parallel Lines */
1191  /* In this case return any point that
1192  * is between the closest segments. */
1193  float a0b1[3], a1b0[3], len_a, len_b, fac1, fac2;
1194  sub_v3_v3v3(a0b1, b1, a0);
1195  sub_v3_v3v3(a1b0, b0, a1);
1196  len_a = len_squared_v3(a_dir);
1197  len_b = len_squared_v3(b_dir);
1198 
1199  if (len_a) {
1200  fac1 = dot_v3v3(a0b0, a_dir);
1201  fac2 = dot_v3v3(a0b1, a_dir);
1202  CLAMP(fac1, 0.0f, len_a);
1203  CLAMP(fac2, 0.0f, len_a);
1204  fac_a = (fac1 + fac2) / (2 * len_a);
1205  }
1206  else {
1207  fac_a = 0.0f;
1208  }
1209 
1210  if (len_b) {
1211  fac1 = -dot_v3v3(a0b0, b_dir);
1212  fac2 = -dot_v3v3(a1b0, b_dir);
1213  CLAMP(fac1, 0.0f, len_b);
1214  CLAMP(fac2, 0.0f, len_b);
1215  fac_b = (fac1 + fac2) / (2 * len_b);
1216  }
1217  else {
1218  fac_b = 0.0f;
1219  }
1220  }
1221  else {
1222  float c[3], cray[3];
1223  sub_v3_v3v3(c, crs_ab, a0b0);
1224 
1225  cross_v3_v3v3(cray, c, b_dir);
1226  fac_a = dot_v3v3(cray, crs_ab) / nlen;
1227 
1228  cross_v3_v3v3(cray, c, a_dir);
1229  fac_b = dot_v3v3(cray, crs_ab) / nlen;
1230 
1231  CLAMP(fac_a, 0.0f, 1.0f);
1232  CLAMP(fac_b, 0.0f, 1.0f);
1233  }
1234 
1235  madd_v3_v3v3fl(r_a, a0, a_dir, fac_a);
1236  madd_v3_v3v3fl(r_b, b0, b_dir, fac_b);
1237 }
1238 
1252 int isect_seg_seg_v2_point_ex(const float v0[2],
1253  const float v1[2],
1254  const float v2[2],
1255  const float v3[2],
1256  const float endpoint_bias,
1257  float r_vi[2])
1258 {
1259  float s10[2], s32[2], s30[2], d;
1260  const float eps = 1e-6f;
1261  const float endpoint_min = -endpoint_bias;
1262  const float endpoint_max = endpoint_bias + 1.0f;
1263 
1264  sub_v2_v2v2(s10, v1, v0);
1265  sub_v2_v2v2(s32, v3, v2);
1266  sub_v2_v2v2(s30, v3, v0);
1267 
1268  d = cross_v2v2(s10, s32);
1269 
1270  if (d != 0) {
1271  float u, v;
1272 
1273  u = cross_v2v2(s30, s32) / d;
1274  v = cross_v2v2(s10, s30) / d;
1275 
1276  if ((u >= endpoint_min && u <= endpoint_max) && (v >= endpoint_min && v <= endpoint_max)) {
1277  /* intersection */
1278  float vi_test[2];
1279  float s_vi_v2[2];
1280 
1281  madd_v2_v2v2fl(vi_test, v0, s10, u);
1282 
1283  /* When 'd' approaches zero, float precision lets non-overlapping co-linear segments
1284  * detect as an intersection. So re-calculate 'v' to ensure the point overlaps both.
1285  * see T45123 */
1286 
1287  /* inline since we have most vars already */
1288 #if 0
1289  v = line_point_factor_v2(ix_test, v2, v3);
1290 #else
1291  sub_v2_v2v2(s_vi_v2, vi_test, v2);
1292  v = (dot_v2v2(s32, s_vi_v2) / dot_v2v2(s32, s32));
1293 #endif
1294  if (v >= endpoint_min && v <= endpoint_max) {
1295  copy_v2_v2(r_vi, vi_test);
1296  return 1;
1297  }
1298  }
1299 
1300  /* out of segment intersection */
1301  return -1;
1302  }
1303 
1304  if ((cross_v2v2(s10, s30) == 0.0f) && (cross_v2v2(s32, s30) == 0.0f)) {
1305  /* equal lines */
1306  float s20[2];
1307  float u_a, u_b;
1308 
1309  if (equals_v2v2(v0, v1)) {
1310  if (len_squared_v2v2(v2, v3) > square_f(eps)) {
1311  /* use non-point segment as basis */
1312  SWAP(const float *, v0, v2);
1313  SWAP(const float *, v1, v3);
1314 
1315  sub_v2_v2v2(s10, v1, v0);
1316  sub_v2_v2v2(s30, v3, v0);
1317  }
1318  else { /* both of segments are points */
1319  if (equals_v2v2(v0, v2)) { /* points are equal */
1320  copy_v2_v2(r_vi, v0);
1321  return 1;
1322  }
1323 
1324  /* two different points */
1325  return -1;
1326  }
1327  }
1328 
1329  sub_v2_v2v2(s20, v2, v0);
1330 
1331  u_a = dot_v2v2(s20, s10) / dot_v2v2(s10, s10);
1332  u_b = dot_v2v2(s30, s10) / dot_v2v2(s10, s10);
1333 
1334  if (u_a > u_b) {
1335  SWAP(float, u_a, u_b);
1336  }
1337 
1338  if (u_a > endpoint_max || u_b < endpoint_min) {
1339  /* non-overlapping segments */
1340  return -1;
1341  }
1342  if (max_ff(0.0f, u_a) == min_ff(1.0f, u_b)) {
1343  /* one common point: can return result */
1344  madd_v2_v2v2fl(r_vi, v0, s10, max_ff(0, u_a));
1345  return 1;
1346  }
1347  }
1348 
1349  /* lines are collinear */
1350  return -1;
1351 }
1352 
1354  const float v0[2], const float v1[2], const float v2[2], const float v3[2], float r_vi[2])
1355 {
1356  const float endpoint_bias = 1e-6f;
1357  return isect_seg_seg_v2_point_ex(v0, v1, v2, v3, endpoint_bias, r_vi);
1358 }
1359 
1360 bool isect_seg_seg_v2_simple(const float v1[2],
1361  const float v2[2],
1362  const float v3[2],
1363  const float v4[2])
1364 {
1365 #define CCW(A, B, C) ((C[1] - A[1]) * (B[0] - A[0]) > (B[1] - A[1]) * (C[0] - A[0]))
1366 
1367  return CCW(v1, v3, v4) != CCW(v2, v3, v4) && CCW(v1, v2, v3) != CCW(v1, v2, v4);
1368 
1369 #undef CCW
1370 }
1371 
1384 int isect_seg_seg_v2_lambda_mu_db(const double v1[2],
1385  const double v2[2],
1386  const double v3[2],
1387  const double v4[2],
1388  double *r_lambda,
1389  double *r_mu)
1390 {
1391  double div, lambda, mu;
1392 
1393  div = (v2[0] - v1[0]) * (v4[1] - v3[1]) - (v2[1] - v1[1]) * (v4[0] - v3[0]);
1394  if (fabs(div) < DBL_EPSILON) {
1395  return ISECT_LINE_LINE_COLINEAR;
1396  }
1397 
1398  lambda = ((v1[1] - v3[1]) * (v4[0] - v3[0]) - (v1[0] - v3[0]) * (v4[1] - v3[1])) / div;
1399 
1400  mu = ((v1[1] - v3[1]) * (v2[0] - v1[0]) - (v1[0] - v3[0]) * (v2[1] - v1[1])) / div;
1401 
1402  if (r_lambda) {
1403  *r_lambda = lambda;
1404  }
1405  if (r_mu) {
1406  *r_mu = mu;
1407  }
1408 
1409  if (lambda >= 0.0 && lambda <= 1.0 && mu >= 0.0 && mu <= 1.0) {
1410  if (lambda == 0.0 || lambda == 1.0 || mu == 0.0 || mu == 1.0) {
1411  return ISECT_LINE_LINE_EXACT;
1412  }
1413  return ISECT_LINE_LINE_CROSS;
1414  }
1415  return ISECT_LINE_LINE_NONE;
1416 }
1417 
1431 int isect_line_sphere_v3(const float l1[3],
1432  const float l2[3],
1433  const float sp[3],
1434  const float r,
1435  float r_p1[3],
1436  float r_p2[3])
1437 {
1438  /* adapted for use in blender by Campbell Barton - 2011
1439  *
1440  * atelier iebele abel - 2001
1441  * <atelier@iebele.nl>
1442  * http://www.iebele.nl
1443  *
1444  * sphere_line_intersection function adapted from:
1445  * http://astronomy.swin.edu.au/pbourke/geometry/sphereline
1446  * Paul Bourke <pbourke@swin.edu.au>
1447  */
1448 
1449  const float ldir[3] = {
1450  l2[0] - l1[0],
1451  l2[1] - l1[1],
1452  l2[2] - l1[2],
1453  };
1454 
1455  const float a = len_squared_v3(ldir);
1456 
1457  const float b = 2.0f * (ldir[0] * (l1[0] - sp[0]) + ldir[1] * (l1[1] - sp[1]) +
1458  ldir[2] * (l1[2] - sp[2]));
1459 
1460  const float c = len_squared_v3(sp) + len_squared_v3(l1) - (2.0f * dot_v3v3(sp, l1)) - (r * r);
1461 
1462  const float i = b * b - 4.0f * a * c;
1463 
1464  float mu;
1465 
1466  if (i < 0.0f) {
1467  /* no intersections */
1468  return 0;
1469  }
1470  if (i == 0.0f) {
1471  /* one intersection */
1472  mu = -b / (2.0f * a);
1473  madd_v3_v3v3fl(r_p1, l1, ldir, mu);
1474  return 1;
1475  }
1476  if (i > 0.0f) {
1477  const float i_sqrt = sqrtf(i); /* avoid calc twice */
1478 
1479  /* first intersection */
1480  mu = (-b + i_sqrt) / (2.0f * a);
1481  madd_v3_v3v3fl(r_p1, l1, ldir, mu);
1482 
1483  /* second intersection */
1484  mu = (-b - i_sqrt) / (2.0f * a);
1485  madd_v3_v3v3fl(r_p2, l1, ldir, mu);
1486  return 2;
1487  }
1488 
1489  /* math domain error - nan */
1490  return -1;
1491 }
1492 
1493 /* keep in sync with isect_line_sphere_v3 */
1494 int isect_line_sphere_v2(const float l1[2],
1495  const float l2[2],
1496  const float sp[2],
1497  const float r,
1498  float r_p1[2],
1499  float r_p2[2])
1500 {
1501  const float ldir[2] = {l2[0] - l1[0], l2[1] - l1[1]};
1502 
1503  const float a = dot_v2v2(ldir, ldir);
1504 
1505  const float b = 2.0f * (ldir[0] * (l1[0] - sp[0]) + ldir[1] * (l1[1] - sp[1]));
1506 
1507  const float c = dot_v2v2(sp, sp) + dot_v2v2(l1, l1) - (2.0f * dot_v2v2(sp, l1)) - (r * r);
1508 
1509  const float i = b * b - 4.0f * a * c;
1510 
1511  float mu;
1512 
1513  if (i < 0.0f) {
1514  /* no intersections */
1515  return 0;
1516  }
1517  if (i == 0.0f) {
1518  /* one intersection */
1519  mu = -b / (2.0f * a);
1520  madd_v2_v2v2fl(r_p1, l1, ldir, mu);
1521  return 1;
1522  }
1523  if (i > 0.0f) {
1524  const float i_sqrt = sqrtf(i); /* avoid calc twice */
1525 
1526  /* first intersection */
1527  mu = (-b + i_sqrt) / (2.0f * a);
1528  madd_v2_v2v2fl(r_p1, l1, ldir, mu);
1529 
1530  /* second intersection */
1531  mu = (-b - i_sqrt) / (2.0f * a);
1532  madd_v2_v2v2fl(r_p2, l1, ldir, mu);
1533  return 2;
1534  }
1535 
1536  /* math domain error - nan */
1537  return -1;
1538 }
1539 
1540 /* point in polygon (keep float and int versions in sync) */
1541 bool isect_point_poly_v2(const float pt[2],
1542  const float verts[][2],
1543  const unsigned int nr,
1544  const bool UNUSED(use_holes))
1545 {
1546  unsigned int i, j;
1547  bool isect = false;
1548  for (i = 0, j = nr - 1; i < nr; j = i++) {
1549  if (((verts[i][1] > pt[1]) != (verts[j][1] > pt[1])) &&
1550  (pt[0] <
1551  (verts[j][0] - verts[i][0]) * (pt[1] - verts[i][1]) / (verts[j][1] - verts[i][1]) +
1552  verts[i][0])) {
1553  isect = !isect;
1554  }
1555  }
1556  return isect;
1557 }
1558 bool isect_point_poly_v2_int(const int pt[2],
1559  const int verts[][2],
1560  const unsigned int nr,
1561  const bool UNUSED(use_holes))
1562 {
1563  unsigned int i, j;
1564  bool isect = false;
1565  for (i = 0, j = nr - 1; i < nr; j = i++) {
1566  if (((verts[i][1] > pt[1]) != (verts[j][1] > pt[1])) &&
1567  (pt[0] <
1568  (verts[j][0] - verts[i][0]) * (pt[1] - verts[i][1]) / (verts[j][1] - verts[i][1]) +
1569  verts[i][0])) {
1570  isect = !isect;
1571  }
1572  }
1573  return isect;
1574 }
1575 
1576 /* point in tri */
1577 
1578 /* only single direction */
1579 bool isect_point_tri_v2_cw(const float pt[2],
1580  const float v1[2],
1581  const float v2[2],
1582  const float v3[2])
1583 {
1584  if (line_point_side_v2(v1, v2, pt) >= 0.0f) {
1585  if (line_point_side_v2(v2, v3, pt) >= 0.0f) {
1586  if (line_point_side_v2(v3, v1, pt) >= 0.0f) {
1587  return true;
1588  }
1589  }
1590  }
1591 
1592  return false;
1593 }
1594 
1595 int isect_point_tri_v2(const float pt[2], const float v1[2], const float v2[2], const float v3[2])
1596 {
1597  if (line_point_side_v2(v1, v2, pt) >= 0.0f) {
1598  if (line_point_side_v2(v2, v3, pt) >= 0.0f) {
1599  if (line_point_side_v2(v3, v1, pt) >= 0.0f) {
1600  return 1;
1601  }
1602  }
1603  }
1604  else {
1605  if (!(line_point_side_v2(v2, v3, pt) >= 0.0f)) {
1606  if (!(line_point_side_v2(v3, v1, pt) >= 0.0f)) {
1607  return -1;
1608  }
1609  }
1610  }
1611 
1612  return 0;
1613 }
1614 
1615 /* point in quad - only convex quads */
1617  const float pt[2], const float v1[2], const float v2[2], const float v3[2], const float v4[2])
1618 {
1619  if (line_point_side_v2(v1, v2, pt) >= 0.0f) {
1620  if (line_point_side_v2(v2, v3, pt) >= 0.0f) {
1621  if (line_point_side_v2(v3, v4, pt) >= 0.0f) {
1622  if (line_point_side_v2(v4, v1, pt) >= 0.0f) {
1623  return 1;
1624  }
1625  }
1626  }
1627  }
1628  else {
1629  if (!(line_point_side_v2(v2, v3, pt) >= 0.0f)) {
1630  if (!(line_point_side_v2(v3, v4, pt) >= 0.0f)) {
1631  if (!(line_point_side_v2(v4, v1, pt) >= 0.0f)) {
1632  return -1;
1633  }
1634  }
1635  }
1636  }
1637 
1638  return 0;
1639 }
1640 
1641 /* moved from effect.c
1642  * test if the line starting at p1 ending at p2 intersects the triangle v0..v2
1643  * return non zero if it does
1644  */
1645 bool isect_line_segment_tri_v3(const float p1[3],
1646  const float p2[3],
1647  const float v0[3],
1648  const float v1[3],
1649  const float v2[3],
1650  float *r_lambda,
1651  float r_uv[2])
1652 {
1653 
1654  float p[3], s[3], d[3], e1[3], e2[3], q[3];
1655  float a, f, u, v;
1656 
1657  sub_v3_v3v3(e1, v1, v0);
1658  sub_v3_v3v3(e2, v2, v0);
1659  sub_v3_v3v3(d, p2, p1);
1660 
1661  cross_v3_v3v3(p, d, e2);
1662  a = dot_v3v3(e1, p);
1663  if (a == 0.0f) {
1664  return false;
1665  }
1666  f = 1.0f / a;
1667 
1668  sub_v3_v3v3(s, p1, v0);
1669 
1670  u = f * dot_v3v3(s, p);
1671  if ((u < 0.0f) || (u > 1.0f)) {
1672  return false;
1673  }
1674 
1675  cross_v3_v3v3(q, s, e1);
1676 
1677  v = f * dot_v3v3(d, q);
1678  if ((v < 0.0f) || ((u + v) > 1.0f)) {
1679  return false;
1680  }
1681 
1682  *r_lambda = f * dot_v3v3(e2, q);
1683  if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) {
1684  return false;
1685  }
1686 
1687  if (r_uv) {
1688  r_uv[0] = u;
1689  r_uv[1] = v;
1690  }
1691 
1692  return true;
1693 }
1694 
1695 /* like isect_line_segment_tri_v3, but allows epsilon tolerance around triangle */
1696 bool isect_line_segment_tri_epsilon_v3(const float p1[3],
1697  const float p2[3],
1698  const float v0[3],
1699  const float v1[3],
1700  const float v2[3],
1701  float *r_lambda,
1702  float r_uv[2],
1703  const float epsilon)
1704 {
1705 
1706  float p[3], s[3], d[3], e1[3], e2[3], q[3];
1707  float a, f, u, v;
1708 
1709  sub_v3_v3v3(e1, v1, v0);
1710  sub_v3_v3v3(e2, v2, v0);
1711  sub_v3_v3v3(d, p2, p1);
1712 
1713  cross_v3_v3v3(p, d, e2);
1714  a = dot_v3v3(e1, p);
1715  if (a == 0.0f) {
1716  return false;
1717  }
1718  f = 1.0f / a;
1719 
1720  sub_v3_v3v3(s, p1, v0);
1721 
1722  u = f * dot_v3v3(s, p);
1723  if ((u < -epsilon) || (u > 1.0f + epsilon)) {
1724  return false;
1725  }
1726 
1727  cross_v3_v3v3(q, s, e1);
1728 
1729  v = f * dot_v3v3(d, q);
1730  if ((v < -epsilon) || ((u + v) > 1.0f + epsilon)) {
1731  return false;
1732  }
1733 
1734  *r_lambda = f * dot_v3v3(e2, q);
1735  if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) {
1736  return false;
1737  }
1738 
1739  if (r_uv) {
1740  r_uv[0] = u;
1741  r_uv[1] = v;
1742  }
1743 
1744  return true;
1745 }
1746 
1747 /* moved from effect.c
1748  * test if the ray starting at p1 going in d direction intersects the triangle v0..v2
1749  * return non zero if it does
1750  */
1751 bool isect_ray_tri_v3(const float ray_origin[3],
1752  const float ray_direction[3],
1753  const float v0[3],
1754  const float v1[3],
1755  const float v2[3],
1756  float *r_lambda,
1757  float r_uv[2])
1758 {
1759  /* note: these values were 0.000001 in 2.4x but for projection snapping on
1760  * a human head (1BU == 1m), subsurf level 2, this gave many errors - campbell */
1761  const float epsilon = 0.00000001f;
1762  float p[3], s[3], e1[3], e2[3], q[3];
1763  float a, f, u, v;
1764 
1765  sub_v3_v3v3(e1, v1, v0);
1766  sub_v3_v3v3(e2, v2, v0);
1767 
1768  cross_v3_v3v3(p, ray_direction, e2);
1769  a = dot_v3v3(e1, p);
1770  if ((a > -epsilon) && (a < epsilon)) {
1771  return false;
1772  }
1773  f = 1.0f / a;
1774 
1775  sub_v3_v3v3(s, ray_origin, v0);
1776 
1777  u = f * dot_v3v3(s, p);
1778  if ((u < 0.0f) || (u > 1.0f)) {
1779  return false;
1780  }
1781 
1782  cross_v3_v3v3(q, s, e1);
1783 
1784  v = f * dot_v3v3(ray_direction, q);
1785  if ((v < 0.0f) || ((u + v) > 1.0f)) {
1786  return false;
1787  }
1788 
1789  *r_lambda = f * dot_v3v3(e2, q);
1790  if ((*r_lambda < 0.0f)) {
1791  return false;
1792  }
1793 
1794  if (r_uv) {
1795  r_uv[0] = u;
1796  r_uv[1] = v;
1797  }
1798 
1799  return true;
1800 }
1801 
1808 bool isect_ray_plane_v3(const float ray_origin[3],
1809  const float ray_direction[3],
1810  const float plane[4],
1811  float *r_lambda,
1812  const bool clip)
1813 {
1814  float h[3], plane_co[3];
1815  float dot;
1816 
1817  dot = dot_v3v3(plane, ray_direction);
1818  if (dot == 0.0f) {
1819  return false;
1820  }
1821  mul_v3_v3fl(plane_co, plane, (-plane[3] / len_squared_v3(plane)));
1822  sub_v3_v3v3(h, ray_origin, plane_co);
1823  *r_lambda = -dot_v3v3(plane, h) / dot;
1824  if (clip && (*r_lambda < 0.0f)) {
1825  return false;
1826  }
1827  return true;
1828 }
1829 
1831  const float ray_direction[3],
1832  const float v0[3],
1833  const float v1[3],
1834  const float v2[3],
1835  float *r_lambda,
1836  float r_uv[2],
1837  const float epsilon)
1838 {
1839  float p[3], s[3], e1[3], e2[3], q[3];
1840  float a, f, u, v;
1841 
1842  sub_v3_v3v3(e1, v1, v0);
1843  sub_v3_v3v3(e2, v2, v0);
1844 
1845  cross_v3_v3v3(p, ray_direction, e2);
1846  a = dot_v3v3(e1, p);
1847  if (a == 0.0f) {
1848  return false;
1849  }
1850  f = 1.0f / a;
1851 
1852  sub_v3_v3v3(s, ray_origin, v0);
1853 
1854  u = f * dot_v3v3(s, p);
1855  if ((u < -epsilon) || (u > 1.0f + epsilon)) {
1856  return false;
1857  }
1858 
1859  cross_v3_v3v3(q, s, e1);
1860 
1861  v = f * dot_v3v3(ray_direction, q);
1862  if ((v < -epsilon) || ((u + v) > 1.0f + epsilon)) {
1863  return false;
1864  }
1865 
1866  *r_lambda = f * dot_v3v3(e2, q);
1867  if ((*r_lambda < 0.0f)) {
1868  return false;
1869  }
1870 
1871  if (r_uv) {
1872  r_uv[0] = u;
1873  r_uv[1] = v;
1874  }
1875 
1876  return true;
1877 }
1878 
1880  const float ray_direction[3])
1881 {
1882  float inv_dir_z;
1883 
1884  /* Calculate dimension where the ray direction is maximal. */
1886  int kx = (kz != 2) ? (kz + 1) : 0;
1887  int ky = (kx != 2) ? (kx + 1) : 0;
1888 
1889  /* Swap kx and ky dimensions to preserve winding direction of triangles. */
1890  if (ray_direction[kz] < 0.0f) {
1891  SWAP(int, kx, ky);
1892  }
1893 
1894  /* Calculate the shear constants. */
1895  inv_dir_z = 1.0f / ray_direction[kz];
1896  isect_precalc->sx = ray_direction[kx] * inv_dir_z;
1897  isect_precalc->sy = ray_direction[ky] * inv_dir_z;
1898  isect_precalc->sz = inv_dir_z;
1899 
1900  /* Store the dimensions. */
1901  isect_precalc->kx = kx;
1902  isect_precalc->ky = ky;
1903  isect_precalc->kz = kz;
1904 }
1905 
1907  const struct IsectRayPrecalc *isect_precalc,
1908  const float v0[3],
1909  const float v1[3],
1910  const float v2[3],
1911  float *r_lambda,
1912  float r_uv[2])
1913 {
1914  const int kx = isect_precalc->kx;
1915  const int ky = isect_precalc->ky;
1916  const int kz = isect_precalc->kz;
1917  const float sx = isect_precalc->sx;
1918  const float sy = isect_precalc->sy;
1919  const float sz = isect_precalc->sz;
1920 
1921  /* Calculate vertices relative to ray origin. */
1922  const float a[3] = {v0[0] - ray_origin[0], v0[1] - ray_origin[1], v0[2] - ray_origin[2]};
1923  const float b[3] = {v1[0] - ray_origin[0], v1[1] - ray_origin[1], v1[2] - ray_origin[2]};
1924  const float c[3] = {v2[0] - ray_origin[0], v2[1] - ray_origin[1], v2[2] - ray_origin[2]};
1925 
1926  const float a_kx = a[kx], a_ky = a[ky], a_kz = a[kz];
1927  const float b_kx = b[kx], b_ky = b[ky], b_kz = b[kz];
1928  const float c_kx = c[kx], c_ky = c[ky], c_kz = c[kz];
1929 
1930  /* Perform shear and scale of vertices. */
1931  const float ax = a_kx - sx * a_kz;
1932  const float ay = a_ky - sy * a_kz;
1933  const float bx = b_kx - sx * b_kz;
1934  const float by = b_ky - sy * b_kz;
1935  const float cx = c_kx - sx * c_kz;
1936  const float cy = c_ky - sy * c_kz;
1937 
1938  /* Calculate scaled barycentric coordinates. */
1939  const float u = cx * by - cy * bx;
1940  const float v = ax * cy - ay * cx;
1941  const float w = bx * ay - by * ax;
1942  float det;
1943 
1944  if ((u < 0.0f || v < 0.0f || w < 0.0f) && (u > 0.0f || v > 0.0f || w > 0.0f)) {
1945  return false;
1946  }
1947 
1948  /* Calculate determinant. */
1949  det = u + v + w;
1950  if (UNLIKELY(det == 0.0f || !isfinite(det))) {
1951  return false;
1952  }
1953 
1954  /* Calculate scaled z-coordinates of vertices and use them to calculate
1955  * the hit distance.
1956  */
1957  const int sign_det = (float_as_int(det) & (int)0x80000000);
1958  const float t = (u * a_kz + v * b_kz + w * c_kz) * sz;
1959  const float sign_t = xor_fl(t, sign_det);
1960  if ((sign_t < 0.0f)
1961  /* Differ from Cycles, don't read r_lambda's original value
1962  * otherwise we won't match any of the other intersect functions here...
1963  * which would be confusing. */
1964 #if 0
1965  || (sign_T > *r_lambda * xor_signmask(det, sign_mask))
1966 #endif
1967  ) {
1968  return false;
1969  }
1970 
1971  /* Normalize u, v and t. */
1972  const float inv_det = 1.0f / det;
1973  if (r_uv) {
1974  r_uv[0] = u * inv_det;
1975  r_uv[1] = v * inv_det;
1976  }
1977  *r_lambda = t * inv_det;
1978  return true;
1979 }
1980 
1982  const float ray_direction[3],
1983  const float v0[3],
1984  const float v1[3],
1985  const float v2[3],
1986  float *r_lambda,
1987  float r_uv[2])
1988 {
1989  struct IsectRayPrecalc isect_precalc;
1990  isect_ray_tri_watertight_v3_precalc(&isect_precalc, ray_direction);
1991  return isect_ray_tri_watertight_v3(ray_origin, &isect_precalc, v0, v1, v2, r_lambda, r_uv);
1992 }
1993 
1994 #if 0 /* UNUSED */
1999 bool isect_ray_tri_threshold_v3(const float ray_origin[3],
2000  const float ray_direction[3],
2001  const float v0[3],
2002  const float v1[3],
2003  const float v2[3],
2004  float *r_lambda,
2005  float r_uv[2],
2006  const float threshold)
2007 {
2008  const float epsilon = 0.00000001f;
2009  float p[3], s[3], e1[3], e2[3], q[3];
2010  float a, f, u, v;
2011  float du, dv;
2012 
2013  sub_v3_v3v3(e1, v1, v0);
2014  sub_v3_v3v3(e2, v2, v0);
2015 
2016  cross_v3_v3v3(p, ray_direction, e2);
2017  a = dot_v3v3(e1, p);
2018  if ((a > -epsilon) && (a < epsilon)) {
2019  return false;
2020  }
2021  f = 1.0f / a;
2022 
2023  sub_v3_v3v3(s, ray_origin, v0);
2024 
2025  cross_v3_v3v3(q, s, e1);
2026  *r_lambda = f * dot_v3v3(e2, q);
2027  if ((*r_lambda < 0.0f)) {
2028  return false;
2029  }
2030 
2031  u = f * dot_v3v3(s, p);
2032  v = f * dot_v3v3(ray_direction, q);
2033 
2034  if (u > 0 && v > 0 && u + v > 1) {
2035  float t = (u + v - 1) / 2;
2036  du = u - t;
2037  dv = v - t;
2038  }
2039  else {
2040  if (u < 0) {
2041  du = u;
2042  }
2043  else if (u > 1) {
2044  du = u - 1;
2045  }
2046  else {
2047  du = 0.0f;
2048  }
2049 
2050  if (v < 0) {
2051  dv = v;
2052  }
2053  else if (v > 1) {
2054  dv = v - 1;
2055  }
2056  else {
2057  dv = 0.0f;
2058  }
2059  }
2060 
2061  mul_v3_fl(e1, du);
2062  mul_v3_fl(e2, dv);
2063 
2064  if (len_squared_v3(e1) + len_squared_v3(e2) > threshold * threshold) {
2065  return false;
2066  }
2067 
2068  if (r_uv) {
2069  r_uv[0] = u;
2070  r_uv[1] = v;
2071  }
2072 
2073  return true;
2074 }
2075 #endif
2076 
2077 bool isect_ray_seg_v2(const float ray_origin[2],
2078  const float ray_direction[2],
2079  const float v0[2],
2080  const float v1[2],
2081  float *r_lambda,
2082  float *r_u)
2083 {
2084  float v0_local[2], v1_local[2];
2085  sub_v2_v2v2(v0_local, v0, ray_origin);
2086  sub_v2_v2v2(v1_local, v1, ray_origin);
2087 
2088  float s10[2];
2089  float det;
2090 
2091  sub_v2_v2v2(s10, v1_local, v0_local);
2092 
2093  det = cross_v2v2(ray_direction, s10);
2094  if (det != 0.0f) {
2095  const float v = cross_v2v2(v0_local, v1_local);
2096  const float p[2] = {(ray_direction[0] * v) / det, (ray_direction[1] * v) / det};
2097 
2098  const float t = (dot_v2v2(p, ray_direction) / dot_v2v2(ray_direction, ray_direction));
2099  if ((t >= 0.0f) == 0) {
2100  return false;
2101  }
2102 
2103  float h[2];
2104  sub_v2_v2v2(h, v1_local, p);
2105  const float u = (dot_v2v2(s10, h) / dot_v2v2(s10, s10));
2106  if ((u >= 0.0f && u <= 1.0f) == 0) {
2107  return false;
2108  }
2109 
2110  if (r_lambda) {
2111  *r_lambda = t;
2112  }
2113  if (r_u) {
2114  *r_u = u;
2115  }
2116 
2117  return true;
2118  }
2119 
2120  return false;
2121 }
2122 
2123 bool isect_ray_line_v3(const float ray_origin[3],
2124  const float ray_direction[3],
2125  const float v0[3],
2126  const float v1[3],
2127  float *r_lambda)
2128 {
2129  float a[3], t[3], n[3];
2130  sub_v3_v3v3(a, v1, v0);
2131  sub_v3_v3v3(t, v0, ray_origin);
2132  cross_v3_v3v3(n, a, ray_direction);
2133  const float nlen = len_squared_v3(n);
2134 
2135  if (nlen == 0.0f) {
2136  /* the lines are parallel.*/
2137  return false;
2138  }
2139 
2140  float c[3], cray[3];
2141  sub_v3_v3v3(c, n, t);
2142  cross_v3_v3v3(cray, c, ray_direction);
2143 
2144  *r_lambda = dot_v3v3(cray, n) / nlen;
2145 
2146  return true;
2147 }
2148 
2152 bool isect_point_planes_v3(float (*planes)[4], int totplane, const float p[3])
2153 {
2154  int i;
2155 
2156  for (i = 0; i < totplane; i++) {
2157  if (plane_point_side_v3(planes[i], p) > 0.0f) {
2158  return false;
2159  }
2160  }
2161 
2162  return true;
2163 }
2164 
2169 bool isect_point_planes_v3_negated(const float (*planes)[4], const int totplane, const float p[3])
2170 {
2171  for (int i = 0; i < totplane; i++) {
2172  if (plane_point_side_v3(planes[i], p) <= 0.0f) {
2173  return false;
2174  }
2175  }
2176 
2177  return true;
2178 }
2179 
2191 bool isect_line_plane_v3(float r_isect_co[3],
2192  const float l1[3],
2193  const float l2[3],
2194  const float plane_co[3],
2195  const float plane_no[3])
2196 {
2197  float u[3], h[3];
2198  float dot;
2199 
2200  sub_v3_v3v3(u, l2, l1);
2201  sub_v3_v3v3(h, l1, plane_co);
2202  dot = dot_v3v3(plane_no, u);
2203 
2204  if (fabsf(dot) > FLT_EPSILON) {
2205  float lambda = -dot_v3v3(plane_no, h) / dot;
2206  madd_v3_v3v3fl(r_isect_co, l1, u, lambda);
2207  return true;
2208  }
2209 
2210  /* The segment is parallel to plane */
2211  return false;
2212 }
2213 
2221 bool isect_plane_plane_plane_v3(const float plane_a[4],
2222  const float plane_b[4],
2223  const float plane_c[4],
2224  float r_isect_co[3])
2225 {
2226  float det;
2227 
2228  det = determinant_m3(UNPACK3(plane_a), UNPACK3(plane_b), UNPACK3(plane_c));
2229 
2230  if (det != 0.0f) {
2231  float tmp[3];
2232 
2233  /* (plane_b.xyz.cross(plane_c.xyz) * -plane_a[3] +
2234  * plane_c.xyz.cross(plane_a.xyz) * -plane_b[3] +
2235  * plane_a.xyz.cross(plane_b.xyz) * -plane_c[3]) / det; */
2236 
2237  cross_v3_v3v3(tmp, plane_c, plane_b);
2238  mul_v3_v3fl(r_isect_co, tmp, plane_a[3]);
2239 
2240  cross_v3_v3v3(tmp, plane_a, plane_c);
2241  madd_v3_v3fl(r_isect_co, tmp, plane_b[3]);
2242 
2243  cross_v3_v3v3(tmp, plane_b, plane_a);
2244  madd_v3_v3fl(r_isect_co, tmp, plane_c[3]);
2245 
2246  mul_v3_fl(r_isect_co, 1.0f / det);
2247 
2248  return true;
2249  }
2250 
2251  return false;
2252 }
2253 
2265 bool isect_plane_plane_v3(const float plane_a[4],
2266  const float plane_b[4],
2267  float r_isect_co[3],
2268  float r_isect_no[3])
2269 {
2270  float det, plane_c[3];
2271 
2272  /* direction is simply the cross product */
2273  cross_v3_v3v3(plane_c, plane_a, plane_b);
2274 
2275  /* in this case we don't need to use 'determinant_m3' */
2276  det = len_squared_v3(plane_c);
2277 
2278  if (det != 0.0f) {
2279  float tmp[3];
2280 
2281  /* (plane_b.xyz.cross(plane_c.xyz) * -plane_a[3] +
2282  * plane_c.xyz.cross(plane_a.xyz) * -plane_b[3]) / det; */
2283  cross_v3_v3v3(tmp, plane_c, plane_b);
2284  mul_v3_v3fl(r_isect_co, tmp, plane_a[3]);
2285 
2286  cross_v3_v3v3(tmp, plane_a, plane_c);
2287  madd_v3_v3fl(r_isect_co, tmp, plane_b[3]);
2288 
2289  mul_v3_fl(r_isect_co, 1.0f / det);
2290 
2291  copy_v3_v3(r_isect_no, plane_c);
2292 
2293  return true;
2294  }
2295 
2296  return false;
2297 }
2298 
2313  const float planes[][4],
2314  const int planes_len,
2315  const float eps_coplanar,
2316  const float eps_isect,
2317  void (*callback_fn)(const float co[3], int i, int j, int k, void *user_data),
2318  void *user_data)
2319 {
2320  bool found = false;
2321 
2322  float n1n2[3], n2n3[3], n3n1[3];
2323 
2324  for (int i = 0; i < planes_len; i++) {
2325  const float *n1 = planes[i];
2326  for (int j = i + 1; j < planes_len; j++) {
2327  const float *n2 = planes[j];
2328  cross_v3_v3v3(n1n2, n1, n2);
2329  if (len_squared_v3(n1n2) <= eps_coplanar) {
2330  continue;
2331  }
2332  for (int k = j + 1; k < planes_len; k++) {
2333  const float *n3 = planes[k];
2334  cross_v3_v3v3(n2n3, n2, n3);
2335  if (len_squared_v3(n2n3) <= eps_coplanar) {
2336  continue;
2337  }
2338 
2339  cross_v3_v3v3(n3n1, n3, n1);
2340  if (len_squared_v3(n3n1) <= eps_coplanar) {
2341  continue;
2342  }
2343  const float quotient = -dot_v3v3(n1, n2n3);
2344  if (fabsf(quotient) < eps_coplanar) {
2345  continue;
2346  }
2347  const float co_test[3] = {
2348  ((n2n3[0] * n1[3]) + (n3n1[0] * n2[3]) + (n1n2[0] * n3[3])) / quotient,
2349  ((n2n3[1] * n1[3]) + (n3n1[1] * n2[3]) + (n1n2[1] * n3[3])) / quotient,
2350  ((n2n3[2] * n1[3]) + (n3n1[2] * n2[3]) + (n1n2[2] * n3[3])) / quotient,
2351  };
2352  int i_test;
2353  for (i_test = 0; i_test < planes_len; i_test++) {
2354  const float *np_test = planes[i_test];
2355  if (((dot_v3v3(np_test, co_test) + np_test[3]) > eps_isect)) {
2356  /* For low epsilon values the point could intersect it's own plane. */
2357  if (!ELEM(i_test, i, j, k)) {
2358  break;
2359  }
2360  }
2361  }
2362 
2363  if (i_test == planes_len) { /* ok */
2364  callback_fn(co_test, i, j, k, user_data);
2365  found = true;
2366  }
2367  }
2368  }
2369  }
2370 
2371  return found;
2372 }
2373 
2384 bool isect_tri_tri_v3_ex(const float tri_a[3][3],
2385  const float tri_b[3][3],
2386  float r_i1[3],
2387  float r_i2[3],
2388  int *r_tri_a_edge_isect_count)
2389 {
2390  struct {
2391  /* Factor that indicates the position of the intersection point on the line
2392  * that intersects the planes of the triangles. */
2393  float min, max;
2394  /* Intersection point location. */
2395  float loc[2][3];
2396  } range[2];
2397 
2398  float side[2][3];
2399  double ba[3], bc[3], plane_a[4], plane_b[4];
2400  *r_tri_a_edge_isect_count = 0;
2401 
2402  sub_v3db_v3fl_v3fl(ba, tri_a[0], tri_a[1]);
2403  sub_v3db_v3fl_v3fl(bc, tri_a[2], tri_a[1]);
2404  cross_v3_v3v3_db(plane_a, ba, bc);
2405  plane_a[3] = -dot_v3db_v3fl(plane_a, tri_a[1]);
2406  side[1][0] = (float)(dot_v3db_v3fl(plane_a, tri_b[0]) + plane_a[3]);
2407  side[1][1] = (float)(dot_v3db_v3fl(plane_a, tri_b[1]) + plane_a[3]);
2408  side[1][2] = (float)(dot_v3db_v3fl(plane_a, tri_b[2]) + plane_a[3]);
2409 
2410  if (!side[1][0] && !side[1][1] && !side[1][2]) {
2411  /* Coplanar case is not supported. */
2412  return false;
2413  }
2414 
2415  if ((side[1][0] && side[1][1] && side[1][2]) && (side[1][0] < 0.0f) == (side[1][1] < 0.0f) &&
2416  (side[1][0] < 0.0f) == (side[1][2] < 0.0f)) {
2417  /* All vertices of the 2nd triangle are positioned on the same side to the
2418  * plane defined by the 1st triangle. */
2419  return false;
2420  }
2421 
2422  sub_v3db_v3fl_v3fl(ba, tri_b[0], tri_b[1]);
2423  sub_v3db_v3fl_v3fl(bc, tri_b[2], tri_b[1]);
2424  cross_v3_v3v3_db(plane_b, ba, bc);
2425  plane_b[3] = -dot_v3db_v3fl(plane_b, tri_b[1]);
2426  side[0][0] = (float)(dot_v3db_v3fl(plane_b, tri_a[0]) + plane_b[3]);
2427  side[0][1] = (float)(dot_v3db_v3fl(plane_b, tri_a[1]) + plane_b[3]);
2428  side[0][2] = (float)(dot_v3db_v3fl(plane_b, tri_a[2]) + plane_b[3]);
2429 
2430  if ((side[0][0] && side[0][1] && side[0][2]) && (side[0][0] < 0.0f) == (side[0][1] < 0.0f) &&
2431  (side[0][0] < 0.0f) == (side[0][2] < 0.0f)) {
2432  /* All vertices of the 1st triangle are positioned on the same side to the
2433  * plane defined by the 2nd triangle. */
2434  return false;
2435  }
2436 
2437  /* Direction of the line that intersects the planes of the triangles. */
2438  double isect_dir[3];
2439  cross_v3_v3v3_db(isect_dir, plane_a, plane_b);
2440  for (int i = 0; i < 2; i++) {
2441  const float(*tri)[3] = i == 0 ? tri_a : tri_b;
2442  /* Rearrange the triangle so that the vertex that is alone on one side
2443  * of the plane is located at index 1. */
2444  int tri_i[3];
2445  if ((side[i][0] && side[i][1]) && (side[i][0] < 0.0f) == (side[i][1] < 0.0f)) {
2446  tri_i[0] = 1;
2447  tri_i[1] = 2;
2448  tri_i[2] = 0;
2449  }
2450  else if ((side[i][1] && side[i][2]) && (side[i][1] < 0.0f) == (side[i][2] < 0.0f)) {
2451  tri_i[0] = 2;
2452  tri_i[1] = 0;
2453  tri_i[2] = 1;
2454  }
2455  else {
2456  tri_i[0] = 0;
2457  tri_i[1] = 1;
2458  tri_i[2] = 2;
2459  }
2460 
2461  double dot_b = dot_v3db_v3fl(isect_dir, tri[tri_i[1]]);
2462  float sidec = side[i][tri_i[1]];
2463  if (sidec) {
2464  double dot_a = dot_v3db_v3fl(isect_dir, tri[tri_i[0]]);
2465  double dot_c = dot_v3db_v3fl(isect_dir, tri[tri_i[2]]);
2466  float fac0 = sidec / (sidec - side[i][tri_i[0]]);
2467  float fac1 = sidec / (sidec - side[i][tri_i[2]]);
2468  double offset0 = fac0 * (dot_a - dot_b);
2469  double offset1 = fac1 * (dot_c - dot_b);
2470  if (offset0 > offset1) {
2471  /* Sort min max. */
2472  SWAP(double, offset0, offset1);
2473  SWAP(float, fac0, fac1);
2474  SWAP(int, tri_i[0], tri_i[2]);
2475  }
2476 
2477  range[i].min = (float)(dot_b + offset0);
2478  range[i].max = (float)(dot_b + offset1);
2479  interp_v3_v3v3(range[i].loc[0], tri[tri_i[1]], tri[tri_i[0]], fac0);
2480  interp_v3_v3v3(range[i].loc[1], tri[tri_i[1]], tri[tri_i[2]], fac1);
2481  }
2482  else {
2483  range[i].min = range[i].max = (float)dot_b;
2484  copy_v3_v3(range[i].loc[0], tri[tri_i[1]]);
2485  copy_v3_v3(range[i].loc[1], tri[tri_i[1]]);
2486  }
2487  }
2488 
2489  if ((range[0].max > range[1].min) && (range[0].min < range[1].max)) {
2490  /* The triangles intersect because they overlap on the intersection line.
2491  * Now identify the two points of intersection that are in the middle to get the actual
2492  * intersection between the triangles. (B--C from A--B--C--D) */
2493  if (range[0].min >= range[1].min) {
2494  copy_v3_v3(r_i1, range[0].loc[0]);
2495  if (range[0].max <= range[1].max) {
2496  copy_v3_v3(r_i2, range[0].loc[1]);
2497  *r_tri_a_edge_isect_count = 2;
2498  }
2499  else {
2500  copy_v3_v3(r_i2, range[1].loc[1]);
2501  *r_tri_a_edge_isect_count = 1;
2502  }
2503  }
2504  else {
2505  if (range[0].max <= range[1].max) {
2506  copy_v3_v3(r_i1, range[0].loc[1]);
2507  copy_v3_v3(r_i2, range[1].loc[0]);
2508  *r_tri_a_edge_isect_count = 1;
2509  }
2510  else {
2511  copy_v3_v3(r_i1, range[1].loc[0]);
2512  copy_v3_v3(r_i2, range[1].loc[1]);
2513  }
2514  }
2515  return true;
2516  }
2517 
2518  return false;
2519 }
2520 
2521 bool isect_tri_tri_v3(const float t_a0[3],
2522  const float t_a1[3],
2523  const float t_a2[3],
2524  const float t_b0[3],
2525  const float t_b1[3],
2526  const float t_b2[3],
2527  float r_i1[3],
2528  float r_i2[3])
2529 {
2530  float tri_a[3][3], tri_b[3][3];
2531  int dummy;
2532  copy_v3_v3(tri_a[0], t_a0);
2533  copy_v3_v3(tri_a[1], t_a1);
2534  copy_v3_v3(tri_a[2], t_a2);
2535  copy_v3_v3(tri_b[0], t_b0);
2536  copy_v3_v3(tri_b[1], t_b1);
2537  copy_v3_v3(tri_b[2], t_b2);
2538  return isect_tri_tri_v3_ex(tri_a, tri_b, r_i1, r_i2, &dummy);
2539 }
2540 
2541 /* -------------------------------------------------------------------- */
2550 static bool isect_tri_tri_v2_impl_vert(const float t_a0[2],
2551  const float t_a1[2],
2552  const float t_a2[2],
2553  const float t_b0[2],
2554  const float t_b1[2],
2555  const float t_b2[2])
2556 {
2557  if (line_point_side_v2(t_b2, t_b0, t_a1) >= 0.0f) {
2558  if (line_point_side_v2(t_b2, t_b1, t_a1) <= 0.0f) {
2559  if (line_point_side_v2(t_a0, t_b0, t_a1) > 0.0f) {
2560  if (line_point_side_v2(t_a0, t_b1, t_a1) <= 0.0f) {
2561  return 1;
2562  }
2563 
2564  return 0;
2565  }
2566 
2567  if (line_point_side_v2(t_a0, t_b0, t_a2) >= 0.0f) {
2568  if (line_point_side_v2(t_a1, t_a2, t_b0) >= 0.0f) {
2569  return 1;
2570  }
2571 
2572  return 0;
2573  }
2574 
2575  return 0;
2576  }
2577  if (line_point_side_v2(t_a0, t_b1, t_a1) <= 0.0f) {
2578  if (line_point_side_v2(t_b2, t_b1, t_a2) <= 0.0f) {
2579  if (line_point_side_v2(t_a1, t_a2, t_b1) >= 0.0f) {
2580  return 1;
2581  }
2582 
2583  return 0;
2584  }
2585 
2586  return 0;
2587  }
2588 
2589  return 0;
2590  }
2591  if (line_point_side_v2(t_b2, t_b0, t_a2) >= 0.0f) {
2592  if (line_point_side_v2(t_a1, t_a2, t_b2) >= 0.0f) {
2593  if (line_point_side_v2(t_a0, t_b0, t_a2) >= 0.0f) {
2594  return 1;
2595  }
2596 
2597  return 0;
2598  }
2599  if (line_point_side_v2(t_a1, t_a2, t_b1) >= 0.0f) {
2600  if (line_point_side_v2(t_b2, t_a2, t_b1) >= 0.0f) {
2601  return 1;
2602  }
2603 
2604  return 0;
2605  }
2606 
2607  return 0;
2608  }
2609 
2610  return 0;
2611 }
2612 
2613 static bool isect_tri_tri_v2_impl_edge(const float t_a0[2],
2614  const float t_a1[2],
2615  const float t_a2[2],
2616  const float t_b0[2],
2617  const float t_b1[2],
2618  const float t_b2[2])
2619 {
2620  UNUSED_VARS(t_b1);
2621 
2622  if (line_point_side_v2(t_b2, t_b0, t_a1) >= 0.0f) {
2623  if (line_point_side_v2(t_a0, t_b0, t_a1) >= 0.0f) {
2624  if (line_point_side_v2(t_a0, t_a1, t_b2) >= 0.0f) {
2625  return 1;
2626  }
2627 
2628  return 0;
2629  }
2630 
2631  if (line_point_side_v2(t_a1, t_a2, t_b0) >= 0.0f) {
2632  if (line_point_side_v2(t_a2, t_a0, t_b0) >= 0.0f) {
2633  return 1;
2634  }
2635 
2636  return 0;
2637  }
2638 
2639  return 0;
2640  }
2641 
2642  if (line_point_side_v2(t_b2, t_b0, t_a2) >= 0.0f) {
2643  if (line_point_side_v2(t_a0, t_b0, t_a2) >= 0.0f) {
2644  if (line_point_side_v2(t_a0, t_a2, t_b2) >= 0.0f) {
2645  return 1;
2646  }
2647 
2648  if (line_point_side_v2(t_a1, t_a2, t_b2) >= 0.0f) {
2649  return 1;
2650  }
2651 
2652  return 0;
2653  }
2654 
2655  return 0;
2656  }
2657 
2658  return 0;
2659 }
2660 
2661 static int isect_tri_tri_impl_ccw_v2(const float t_a0[2],
2662  const float t_a1[2],
2663  const float t_a2[2],
2664  const float t_b0[2],
2665  const float t_b1[2],
2666  const float t_b2[2])
2667 {
2668  if (line_point_side_v2(t_b0, t_b1, t_a0) >= 0.0f) {
2669  if (line_point_side_v2(t_b1, t_b2, t_a0) >= 0.0f) {
2670  if (line_point_side_v2(t_b2, t_b0, t_a0) >= 0.0f) {
2671  return 1;
2672  }
2673 
2674  return isect_tri_tri_v2_impl_edge(t_a0, t_a1, t_a2, t_b0, t_b1, t_b2);
2675  }
2676 
2677  if (line_point_side_v2(t_b2, t_b0, t_a0) >= 0.0f) {
2678  return isect_tri_tri_v2_impl_edge(t_a0, t_a1, t_a2, t_b2, t_b0, t_b1);
2679  }
2680 
2681  return isect_tri_tri_v2_impl_vert(t_a0, t_a1, t_a2, t_b0, t_b1, t_b2);
2682  }
2683 
2684  if (line_point_side_v2(t_b1, t_b2, t_a0) >= 0.0f) {
2685  if (line_point_side_v2(t_b2, t_b0, t_a0) >= 0.0f) {
2686  return isect_tri_tri_v2_impl_edge(t_a0, t_a1, t_a2, t_b1, t_b2, t_b0);
2687  }
2688 
2689  return isect_tri_tri_v2_impl_vert(t_a0, t_a1, t_a2, t_b1, t_b2, t_b0);
2690  }
2691 
2692  return isect_tri_tri_v2_impl_vert(t_a0, t_a1, t_a2, t_b2, t_b0, t_b1);
2693 }
2694 
2695 bool isect_tri_tri_v2(const float t_a0[2],
2696  const float t_a1[2],
2697  const float t_a2[2],
2698  const float t_b0[2],
2699  const float t_b1[2],
2700  const float t_b2[2])
2701 {
2702  if (line_point_side_v2(t_a0, t_a1, t_a2) < 0.0f) {
2703  if (line_point_side_v2(t_b0, t_b1, t_b2) < 0.0f) {
2704  return isect_tri_tri_impl_ccw_v2(t_a0, t_a2, t_a1, t_b0, t_b2, t_b1);
2705  }
2706 
2707  return isect_tri_tri_impl_ccw_v2(t_a0, t_a2, t_a1, t_b0, t_b1, t_b2);
2708  }
2709 
2710  if (line_point_side_v2(t_b0, t_b1, t_b2) < 0.0f) {
2711  return isect_tri_tri_impl_ccw_v2(t_a0, t_a1, t_a2, t_b0, t_b2, t_b1);
2712  }
2713 
2714  return isect_tri_tri_impl_ccw_v2(t_a0, t_a1, t_a2, t_b0, t_b1, t_b2);
2715 }
2716 
2719 /* Adapted from the paper by Kasper Fauerby */
2720 
2721 /* "Improved Collision detection and Response" */
2722 static bool getLowestRoot(
2723  const float a, const float b, const float c, const float maxR, float *root)
2724 {
2725  /* Check if a solution exists */
2726  const float determinant = b * b - 4.0f * a * c;
2727 
2728  /* If determinant is negative it means no solutions. */
2729  if (determinant >= 0.0f) {
2730  /* calculate the two roots: (if determinant == 0 then
2731  * x1==x2 but lets disregard that slight optimization) */
2732  const float sqrtD = sqrtf(determinant);
2733  float r1 = (-b - sqrtD) / (2.0f * a);
2734  float r2 = (-b + sqrtD) / (2.0f * a);
2735 
2736  /* Sort so x1 <= x2 */
2737  if (r1 > r2) {
2738  SWAP(float, r1, r2);
2739  }
2740 
2741  /* Get lowest root: */
2742  if (r1 > 0.0f && r1 < maxR) {
2743  *root = r1;
2744  return true;
2745  }
2746 
2747  /* It is possible that we want x2 - this can happen */
2748  /* if x1 < 0 */
2749  if (r2 > 0.0f && r2 < maxR) {
2750  *root = r2;
2751  return true;
2752  }
2753  }
2754  /* No (valid) solutions */
2755  return false;
2756 }
2757 
2766 int isect_aabb_planes_v3(const float (*planes)[4],
2767  const int totplane,
2768  const float bbmin[3],
2769  const float bbmax[3])
2770 {
2772 
2773  float bb_near[3], bb_far[3];
2774  for (int i = 0; i < totplane; i++) {
2775  aabb_get_near_far_from_plane(planes[i], bbmin, bbmax, bb_near, bb_far);
2776 
2777  if (plane_point_side_v3(planes[i], bb_far) < 0.0f) {
2779  }
2780  if ((ret != ISECT_AABB_PLANE_CROSS_ANY) && (plane_point_side_v3(planes[i], bb_near) < 0.0f)) {
2782  }
2783  }
2784 
2785  return ret;
2786 }
2787 
2788 bool isect_sweeping_sphere_tri_v3(const float p1[3],
2789  const float p2[3],
2790  const float radius,
2791  const float v0[3],
2792  const float v1[3],
2793  const float v2[3],
2794  float *r_lambda,
2795  float ipoint[3])
2796 {
2797  float e1[3], e2[3], e3[3], point[3], vel[3], /*dist[3],*/ nor[3], temp[3], bv[3];
2798  float a, b, c, d, e, x, y, z, radius2 = radius * radius;
2799  float elen2, edotv, edotbv, nordotv;
2800  float newLambda;
2801  bool found_by_sweep = false;
2802 
2803  sub_v3_v3v3(e1, v1, v0);
2804  sub_v3_v3v3(e2, v2, v0);
2805  sub_v3_v3v3(vel, p2, p1);
2806 
2807  /*---test plane of tri---*/
2808  cross_v3_v3v3(nor, e1, e2);
2809  normalize_v3(nor);
2810 
2811  /* flip normal */
2812  if (dot_v3v3(nor, vel) > 0.0f) {
2813  negate_v3(nor);
2814  }
2815 
2816  a = dot_v3v3(p1, nor) - dot_v3v3(v0, nor);
2817  nordotv = dot_v3v3(nor, vel);
2818 
2819  if (fabsf(nordotv) < 0.000001f) {
2820  if (fabsf(a) >= radius) {
2821  return false;
2822  }
2823  }
2824  else {
2825  float t0 = (-a + radius) / nordotv;
2826  float t1 = (-a - radius) / nordotv;
2827 
2828  if (t0 > t1) {
2829  SWAP(float, t0, t1);
2830  }
2831 
2832  if (t0 > 1.0f || t1 < 0.0f) {
2833  return false;
2834  }
2835 
2836  /* clamp to [0, 1] */
2837  CLAMP(t0, 0.0f, 1.0f);
2838  CLAMP(t1, 0.0f, 1.0f);
2839 
2840  /*---test inside of tri---*/
2841  /* plane intersection point */
2842 
2843  point[0] = p1[0] + vel[0] * t0 - nor[0] * radius;
2844  point[1] = p1[1] + vel[1] * t0 - nor[1] * radius;
2845  point[2] = p1[2] + vel[2] * t0 - nor[2] * radius;
2846 
2847  /* is the point in the tri? */
2848  a = dot_v3v3(e1, e1);
2849  b = dot_v3v3(e1, e2);
2850  c = dot_v3v3(e2, e2);
2851 
2852  sub_v3_v3v3(temp, point, v0);
2853  d = dot_v3v3(temp, e1);
2854  e = dot_v3v3(temp, e2);
2855 
2856  x = d * c - e * b;
2857  y = e * a - d * b;
2858  z = x + y - (a * c - b * b);
2859 
2860  if (z <= 0.0f && (x >= 0.0f && y >= 0.0f)) {
2861  //(((unsigned int)z)& ~(((unsigned int)x)|((unsigned int)y))) & 0x80000000) {
2862  *r_lambda = t0;
2863  copy_v3_v3(ipoint, point);
2864  return true;
2865  }
2866  }
2867 
2868  *r_lambda = 1.0f;
2869 
2870  /*---test points---*/
2871  a = dot_v3v3(vel, vel);
2872 
2873  /*v0*/
2874  sub_v3_v3v3(temp, p1, v0);
2875  b = 2.0f * dot_v3v3(vel, temp);
2876  c = dot_v3v3(temp, temp) - radius2;
2877 
2878  if (getLowestRoot(a, b, c, *r_lambda, r_lambda)) {
2879  copy_v3_v3(ipoint, v0);
2880  found_by_sweep = true;
2881  }
2882 
2883  /*v1*/
2884  sub_v3_v3v3(temp, p1, v1);
2885  b = 2.0f * dot_v3v3(vel, temp);
2886  c = dot_v3v3(temp, temp) - radius2;
2887 
2888  if (getLowestRoot(a, b, c, *r_lambda, r_lambda)) {
2889  copy_v3_v3(ipoint, v1);
2890  found_by_sweep = true;
2891  }
2892 
2893  /*v2*/
2894  sub_v3_v3v3(temp, p1, v2);
2895  b = 2.0f * dot_v3v3(vel, temp);
2896  c = dot_v3v3(temp, temp) - radius2;
2897 
2898  if (getLowestRoot(a, b, c, *r_lambda, r_lambda)) {
2899  copy_v3_v3(ipoint, v2);
2900  found_by_sweep = true;
2901  }
2902 
2903  /*---test edges---*/
2904  sub_v3_v3v3(e3, v2, v1); /* wasn't yet calculated */
2905 
2906  /*e1*/
2907  sub_v3_v3v3(bv, v0, p1);
2908 
2909  elen2 = dot_v3v3(e1, e1);
2910  edotv = dot_v3v3(e1, vel);
2911  edotbv = dot_v3v3(e1, bv);
2912 
2913  a = elen2 * (-dot_v3v3(vel, vel)) + edotv * edotv;
2914  b = 2.0f * (elen2 * dot_v3v3(vel, bv) - edotv * edotbv);
2915  c = elen2 * (radius2 - dot_v3v3(bv, bv)) + edotbv * edotbv;
2916 
2917  if (getLowestRoot(a, b, c, *r_lambda, &newLambda)) {
2918  e = (edotv * newLambda - edotbv) / elen2;
2919 
2920  if (e >= 0.0f && e <= 1.0f) {
2921  *r_lambda = newLambda;
2922  copy_v3_v3(ipoint, e1);
2923  mul_v3_fl(ipoint, e);
2924  add_v3_v3(ipoint, v0);
2925  found_by_sweep = true;
2926  }
2927  }
2928 
2929  /*e2*/
2930  /*bv is same*/
2931  elen2 = dot_v3v3(e2, e2);
2932  edotv = dot_v3v3(e2, vel);
2933  edotbv = dot_v3v3(e2, bv);
2934 
2935  a = elen2 * (-dot_v3v3(vel, vel)) + edotv * edotv;
2936  b = 2.0f * (elen2 * dot_v3v3(vel, bv) - edotv * edotbv);
2937  c = elen2 * (radius2 - dot_v3v3(bv, bv)) + edotbv * edotbv;
2938 
2939  if (getLowestRoot(a, b, c, *r_lambda, &newLambda)) {
2940  e = (edotv * newLambda - edotbv) / elen2;
2941 
2942  if (e >= 0.0f && e <= 1.0f) {
2943  *r_lambda = newLambda;
2944  copy_v3_v3(ipoint, e2);
2945  mul_v3_fl(ipoint, e);
2946  add_v3_v3(ipoint, v0);
2947  found_by_sweep = true;
2948  }
2949  }
2950 
2951  /*e3*/
2952  /* sub_v3_v3v3(bv, v0, p1); */ /* UNUSED */
2953  /* elen2 = dot_v3v3(e1, e1); */ /* UNUSED */
2954  /* edotv = dot_v3v3(e1, vel); */ /* UNUSED */
2955  /* edotbv = dot_v3v3(e1, bv); */ /* UNUSED */
2956 
2957  sub_v3_v3v3(bv, v1, p1);
2958  elen2 = dot_v3v3(e3, e3);
2959  edotv = dot_v3v3(e3, vel);
2960  edotbv = dot_v3v3(e3, bv);
2961 
2962  a = elen2 * (-dot_v3v3(vel, vel)) + edotv * edotv;
2963  b = 2.0f * (elen2 * dot_v3v3(vel, bv) - edotv * edotbv);
2964  c = elen2 * (radius2 - dot_v3v3(bv, bv)) + edotbv * edotbv;
2965 
2966  if (getLowestRoot(a, b, c, *r_lambda, &newLambda)) {
2967  e = (edotv * newLambda - edotbv) / elen2;
2968 
2969  if (e >= 0.0f && e <= 1.0f) {
2970  *r_lambda = newLambda;
2971  copy_v3_v3(ipoint, e3);
2972  mul_v3_fl(ipoint, e);
2973  add_v3_v3(ipoint, v1);
2974  found_by_sweep = true;
2975  }
2976  }
2977 
2978  return found_by_sweep;
2979 }
2980 
2982  const float p1[3],
2983  const float p2[3],
2984  const float v0[3],
2985  const float v1[3],
2986  const float v2[3],
2987  float *r_lambda)
2988 {
2989  const float epsilon = 0.000001f;
2990  float p[3], e1[3], e2[3];
2991  float u, v, f;
2992  int a0 = axis, a1 = (axis + 1) % 3, a2 = (axis + 2) % 3;
2993 
2994  sub_v3_v3v3(e1, v1, v0);
2995  sub_v3_v3v3(e2, v2, v0);
2996  sub_v3_v3v3(p, v0, p1);
2997 
2998  f = (e2[a1] * e1[a2] - e2[a2] * e1[a1]);
2999  if ((f > -epsilon) && (f < epsilon)) {
3000  return false;
3001  }
3002 
3003  v = (p[a2] * e1[a1] - p[a1] * e1[a2]) / f;
3004  if ((v < 0.0f) || (v > 1.0f)) {
3005  return false;
3006  }
3007 
3008  f = e1[a1];
3009  if ((f > -epsilon) && (f < epsilon)) {
3010  f = e1[a2];
3011  if ((f > -epsilon) && (f < epsilon)) {
3012  return false;
3013  }
3014  u = (-p[a2] - v * e2[a2]) / f;
3015  }
3016  else {
3017  u = (-p[a1] - v * e2[a1]) / f;
3018  }
3019 
3020  if ((u < 0.0f) || ((u + v) > 1.0f)) {
3021  return false;
3022  }
3023 
3024  *r_lambda = (p[a0] + u * e1[a0] + v * e2[a0]) / (p2[a0] - p1[a0]);
3025 
3026  if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) {
3027  return false;
3028  }
3029 
3030  return true;
3031 }
3032 
3039 int isect_line_line_epsilon_v3(const float v1[3],
3040  const float v2[3],
3041  const float v3[3],
3042  const float v4[3],
3043  float r_i1[3],
3044  float r_i2[3],
3045  const float epsilon)
3046 {
3047  float a[3], b[3], c[3], ab[3], cb[3];
3048  float d, div;
3049 
3050  sub_v3_v3v3(c, v3, v1);
3051  sub_v3_v3v3(a, v2, v1);
3052  sub_v3_v3v3(b, v4, v3);
3053 
3054  cross_v3_v3v3(ab, a, b);
3055  d = dot_v3v3(c, ab);
3056  div = dot_v3v3(ab, ab);
3057 
3058  /* important not to use an epsilon here, see: T45919 */
3059  /* test zero length line */
3060  if (UNLIKELY(div == 0.0f)) {
3061  return 0;
3062  }
3063  /* test if the two lines are coplanar */
3064  if (UNLIKELY(fabsf(d) <= epsilon)) {
3065  cross_v3_v3v3(cb, c, b);
3066 
3067  mul_v3_fl(a, dot_v3v3(cb, ab) / div);
3068  add_v3_v3v3(r_i1, v1, a);
3069  copy_v3_v3(r_i2, r_i1);
3070 
3071  return 1; /* one intersection only */
3072  }
3073  /* if not */
3074 
3075  float n[3], t[3];
3076  float v3t[3], v4t[3];
3077  sub_v3_v3v3(t, v1, v3);
3078 
3079  /* offset between both plane where the lines lies */
3080  cross_v3_v3v3(n, a, b);
3081  project_v3_v3v3(t, t, n);
3082 
3083  /* for the first line, offset the second line until it is coplanar */
3084  add_v3_v3v3(v3t, v3, t);
3085  add_v3_v3v3(v4t, v4, t);
3086 
3087  sub_v3_v3v3(c, v3t, v1);
3088  sub_v3_v3v3(a, v2, v1);
3089  sub_v3_v3v3(b, v4t, v3t);
3090 
3091  cross_v3_v3v3(ab, a, b);
3092  cross_v3_v3v3(cb, c, b);
3093 
3094  mul_v3_fl(a, dot_v3v3(cb, ab) / dot_v3v3(ab, ab));
3095  add_v3_v3v3(r_i1, v1, a);
3096 
3097  /* for the second line, just subtract the offset from the first intersection point */
3098  sub_v3_v3v3(r_i2, r_i1, t);
3099 
3100  return 2; /* two nearest points */
3101 }
3102 
3103 int isect_line_line_v3(const float v1[3],
3104  const float v2[3],
3105  const float v3[3],
3106  const float v4[3],
3107  float r_i1[3],
3108  float r_i2[3])
3109 {
3110  const float epsilon = 0.000001f;
3111  return isect_line_line_epsilon_v3(v1, v2, v3, v4, r_i1, r_i2, epsilon);
3112 }
3113 
3118 bool isect_line_line_strict_v3(const float v1[3],
3119  const float v2[3],
3120  const float v3[3],
3121  const float v4[3],
3122  float vi[3],
3123  float *r_lambda)
3124 {
3125  const float epsilon = 0.000001f;
3126  float a[3], b[3], c[3], ab[3], cb[3], ca[3];
3127  float d, div;
3128 
3129  sub_v3_v3v3(c, v3, v1);
3130  sub_v3_v3v3(a, v2, v1);
3131  sub_v3_v3v3(b, v4, v3);
3132 
3133  cross_v3_v3v3(ab, a, b);
3134  d = dot_v3v3(c, ab);
3135  div = dot_v3v3(ab, ab);
3136 
3137  /* important not to use an epsilon here, see: T45919 */
3138  /* test zero length line */
3139  if (UNLIKELY(div == 0.0f)) {
3140  return false;
3141  }
3142  /* test if the two lines are coplanar */
3143  if (UNLIKELY(fabsf(d) < epsilon)) {
3144  return false;
3145  }
3146 
3147  float f1, f2;
3148  cross_v3_v3v3(cb, c, b);
3149  cross_v3_v3v3(ca, c, a);
3150 
3151  f1 = dot_v3v3(cb, ab) / div;
3152  f2 = dot_v3v3(ca, ab) / div;
3153 
3154  if (f1 >= 0 && f1 <= 1 && f2 >= 0 && f2 <= 1) {
3155  mul_v3_fl(a, f1);
3156  add_v3_v3v3(vi, v1, a);
3157 
3158  if (r_lambda) {
3159  *r_lambda = f1;
3160  }
3161 
3162  return true; /* intersection found */
3163  }
3164 
3165  return false;
3166 }
3167 
3174 bool isect_ray_ray_epsilon_v3(const float ray_origin_a[3],
3175  const float ray_direction_a[3],
3176  const float ray_origin_b[3],
3177  const float ray_direction_b[3],
3178  const float epsilon,
3179  float *r_lambda_a,
3180  float *r_lambda_b)
3181 {
3182  BLI_assert(r_lambda_a || r_lambda_b);
3183  float n[3];
3184  cross_v3_v3v3(n, ray_direction_b, ray_direction_a);
3185  const float nlen = len_squared_v3(n);
3186 
3187  /* `nlen` is the square of the area formed by the two vectors. */
3188  if (UNLIKELY(nlen < epsilon)) {
3189  /* The lines are parallel. */
3190  return false;
3191  }
3192 
3193  float t[3], c[3], cray[3];
3194  sub_v3_v3v3(t, ray_origin_b, ray_origin_a);
3195  sub_v3_v3v3(c, n, t);
3196 
3197  if (r_lambda_a != NULL) {
3198  cross_v3_v3v3(cray, c, ray_direction_b);
3199  *r_lambda_a = dot_v3v3(cray, n) / nlen;
3200  }
3201 
3202  if (r_lambda_b != NULL) {
3203  cross_v3_v3v3(cray, c, ray_direction_a);
3204  *r_lambda_b = dot_v3v3(cray, n) / nlen;
3205  }
3206 
3207  return true;
3208 }
3209 
3210 bool isect_ray_ray_v3(const float ray_origin_a[3],
3211  const float ray_direction_a[3],
3212  const float ray_origin_b[3],
3213  const float ray_direction_b[3],
3214  float *r_lambda_a,
3215  float *r_lambda_b)
3216 {
3217  return isect_ray_ray_epsilon_v3(ray_origin_a,
3218  ray_direction_a,
3219  ray_origin_b,
3220  ray_direction_b,
3221  FLT_MIN,
3222  r_lambda_a,
3223  r_lambda_b);
3224 }
3225 
3226 bool isect_aabb_aabb_v3(const float min1[3],
3227  const float max1[3],
3228  const float min2[3],
3229  const float max2[3])
3230 {
3231  return (min1[0] < max2[0] && min1[1] < max2[1] && min1[2] < max2[2] && min2[0] < max1[0] &&
3232  min2[1] < max1[1] && min2[2] < max1[2]);
3233 }
3234 
3236  const float ray_origin[3],
3237  const float ray_direction[3])
3238 {
3239  copy_v3_v3(data->ray_origin, ray_origin);
3240 
3241  data->ray_inv_dir[0] = 1.0f / ray_direction[0];
3242  data->ray_inv_dir[1] = 1.0f / ray_direction[1];
3243  data->ray_inv_dir[2] = 1.0f / ray_direction[2];
3244 
3245  data->sign[0] = data->ray_inv_dir[0] < 0.0f;
3246  data->sign[1] = data->ray_inv_dir[1] < 0.0f;
3247  data->sign[2] = data->ray_inv_dir[2] < 0.0f;
3248 }
3249 
3250 /* Adapted from http://www.gamedev.net/community/forums/topic.asp?topic_id=459973 */
3252  const float bb_min[3],
3253  const float bb_max[3],
3254  float *tmin_out)
3255 {
3256  float bbox[2][3];
3257 
3258  copy_v3_v3(bbox[0], bb_min);
3259  copy_v3_v3(bbox[1], bb_max);
3260 
3261  float tmin = (bbox[data->sign[0]][0] - data->ray_origin[0]) * data->ray_inv_dir[0];
3262  float tmax = (bbox[1 - data->sign[0]][0] - data->ray_origin[0]) * data->ray_inv_dir[0];
3263 
3264  const float tymin = (bbox[data->sign[1]][1] - data->ray_origin[1]) * data->ray_inv_dir[1];
3265  const float tymax = (bbox[1 - data->sign[1]][1] - data->ray_origin[1]) * data->ray_inv_dir[1];
3266 
3267  if ((tmin > tymax) || (tymin > tmax)) {
3268  return false;
3269  }
3270 
3271  if (tymin > tmin) {
3272  tmin = tymin;
3273  }
3274 
3275  if (tymax < tmax) {
3276  tmax = tymax;
3277  }
3278 
3279  const float tzmin = (bbox[data->sign[2]][2] - data->ray_origin[2]) * data->ray_inv_dir[2];
3280  const float tzmax = (bbox[1 - data->sign[2]][2] - data->ray_origin[2]) * data->ray_inv_dir[2];
3281 
3282  if ((tmin > tzmax) || (tzmin > tmax)) {
3283  return false;
3284  }
3285 
3286  if (tzmin > tmin) {
3287  tmin = tzmin;
3288  }
3289 
3290  /* Note: tmax does not need to be updated since we don't use it
3291  * keeping this here for future reference - jwilkins */
3292  // if (tzmax < tmax) tmax = tzmax;
3293 
3294  if (tmin_out) {
3295  (*tmin_out) = tmin;
3296  }
3297 
3298  return true;
3299 }
3300 
3308 bool isect_ray_aabb_v3_simple(const float orig[3],
3309  const float dir[3],
3310  const float bb_min[3],
3311  const float bb_max[3],
3312  float *tmin,
3313  float *tmax)
3314 {
3315  double t[6];
3316  float hit_dist[2];
3317  const double invdirx = (dir[0] > 1e-35f || dir[0] < -1e-35f) ? 1.0 / (double)dir[0] : DBL_MAX;
3318  const double invdiry = (dir[1] > 1e-35f || dir[1] < -1e-35f) ? 1.0 / (double)dir[1] : DBL_MAX;
3319  const double invdirz = (dir[2] > 1e-35f || dir[2] < -1e-35f) ? 1.0 / (double)dir[2] : DBL_MAX;
3320  t[0] = (double)(bb_min[0] - orig[0]) * invdirx;
3321  t[1] = (double)(bb_max[0] - orig[0]) * invdirx;
3322  t[2] = (double)(bb_min[1] - orig[1]) * invdiry;
3323  t[3] = (double)(bb_max[1] - orig[1]) * invdiry;
3324  t[4] = (double)(bb_min[2] - orig[2]) * invdirz;
3325  t[5] = (double)(bb_max[2] - orig[2]) * invdirz;
3326  hit_dist[0] = (float)fmax(fmax(fmin(t[0], t[1]), fmin(t[2], t[3])), fmin(t[4], t[5]));
3327  hit_dist[1] = (float)fmin(fmin(fmax(t[0], t[1]), fmax(t[2], t[3])), fmax(t[4], t[5]));
3328  if ((hit_dist[1] < 0.0f || hit_dist[0] > hit_dist[1])) {
3329  return false;
3330  }
3331 
3332  if (tmin) {
3333  *tmin = hit_dist[0];
3334  }
3335  if (tmax) {
3336  *tmax = hit_dist[1];
3337  }
3338  return true;
3339 }
3340 
3341 float closest_to_ray_v3(float r_close[3],
3342  const float p[3],
3343  const float ray_orig[3],
3344  const float ray_dir[3])
3345 {
3346  float h[3], lambda;
3347 
3348  if (UNLIKELY(is_zero_v3(ray_dir))) {
3349  lambda = 0.0f;
3350  copy_v3_v3(r_close, ray_orig);
3351  return lambda;
3352  }
3353 
3354  sub_v3_v3v3(h, p, ray_orig);
3355  lambda = dot_v3v3(ray_dir, h) / dot_v3v3(ray_dir, ray_dir);
3356  madd_v3_v3v3fl(r_close, ray_orig, ray_dir, lambda);
3357  return lambda;
3358 }
3359 
3364 float closest_to_line_v3(float r_close[3], const float p[3], const float l1[3], const float l2[3])
3365 {
3366  float u[3];
3367  sub_v3_v3v3(u, l2, l1);
3368  return closest_to_ray_v3(r_close, p, l1, u);
3369 }
3370 
3371 float closest_to_line_v2(float r_close[2], const float p[2], const float l1[2], const float l2[2])
3372 {
3373  float h[2], u[2], lambda, denom;
3374  sub_v2_v2v2(u, l2, l1);
3375  sub_v2_v2v2(h, p, l1);
3376  denom = dot_v2v2(u, u);
3377  if (denom == 0.0f) {
3378  r_close[0] = l1[0];
3379  r_close[1] = l1[1];
3380  return 0.0f;
3381  }
3382  lambda = dot_v2v2(u, h) / denom;
3383  r_close[0] = l1[0] + u[0] * lambda;
3384  r_close[1] = l1[1] + u[1] * lambda;
3385  return lambda;
3386 }
3387 
3388 double closest_to_line_v2_db(double r_close[2],
3389  const double p[2],
3390  const double l1[2],
3391  const double l2[2])
3392 {
3393  double h[2], u[2], lambda, denom;
3394  sub_v2_v2v2_db(u, l2, l1);
3395  sub_v2_v2v2_db(h, p, l1);
3396  denom = dot_v2v2_db(u, u);
3397  if (denom == 0.0) {
3398  r_close[0] = l1[0];
3399  r_close[1] = l1[1];
3400  return 0.0;
3401  }
3402  lambda = dot_v2v2_db(u, h) / denom;
3403  r_close[0] = l1[0] + u[0] * lambda;
3404  r_close[1] = l1[1] + u[1] * lambda;
3405  return lambda;
3406 }
3407 
3408 float ray_point_factor_v3_ex(const float p[3],
3409  const float ray_origin[3],
3410  const float ray_direction[3],
3411  const float epsilon,
3412  const float fallback)
3413 {
3414  float p_relative[3];
3415  sub_v3_v3v3(p_relative, p, ray_origin);
3416  const float dot = len_squared_v3(ray_direction);
3417  return (dot > epsilon) ? (dot_v3v3(ray_direction, p_relative) / dot) : fallback;
3418 }
3419 
3420 float ray_point_factor_v3(const float p[3],
3421  const float ray_origin[3],
3422  const float ray_direction[3])
3423 {
3424  return ray_point_factor_v3_ex(p, ray_origin, ray_direction, 0.0f, 0.0f);
3425 }
3426 
3434 float line_point_factor_v3_ex(const float p[3],
3435  const float l1[3],
3436  const float l2[3],
3437  const float epsilon,
3438  const float fallback)
3439 {
3440  float h[3], u[3];
3441  float dot;
3442  sub_v3_v3v3(u, l2, l1);
3443  sub_v3_v3v3(h, p, l1);
3444 
3445  /* better check for zero */
3446  dot = len_squared_v3(u);
3447  return (dot > epsilon) ? (dot_v3v3(u, h) / dot) : fallback;
3448 }
3449 float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3])
3450 {
3451  return line_point_factor_v3_ex(p, l1, l2, 0.0f, 0.0f);
3452 }
3453 
3454 float line_point_factor_v2_ex(const float p[2],
3455  const float l1[2],
3456  const float l2[2],
3457  const float epsilon,
3458  const float fallback)
3459 {
3460  float h[2], u[2];
3461  float dot;
3462  sub_v2_v2v2(u, l2, l1);
3463  sub_v2_v2v2(h, p, l1);
3464  /* better check for zero */
3465  dot = len_squared_v2(u);
3466  return (dot > epsilon) ? (dot_v2v2(u, h) / dot) : fallback;
3467 }
3468 
3469 float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2])
3470 {
3471  return line_point_factor_v2_ex(p, l1, l2, 0.0f, 0.0f);
3472 }
3473 
3477 float line_plane_factor_v3(const float plane_co[3],
3478  const float plane_no[3],
3479  const float l1[3],
3480  const float l2[3])
3481 {
3482  float u[3], h[3];
3483  float dot;
3484  sub_v3_v3v3(u, l2, l1);
3485  sub_v3_v3v3(h, l1, plane_co);
3486  dot = dot_v3v3(plane_no, u);
3487  return (dot != 0.0f) ? -dot_v3v3(plane_no, h) / dot : 0.0f;
3488 }
3489 
3494 void limit_dist_v3(float v1[3], float v2[3], const float dist)
3495 {
3496  const float dist_old = len_v3v3(v1, v2);
3497 
3498  if (dist_old > dist) {
3499  float v1_old[3];
3500  float v2_old[3];
3501  float fac = (dist / dist_old) * 0.5f;
3502 
3503  copy_v3_v3(v1_old, v1);
3504  copy_v3_v3(v2_old, v2);
3505 
3506  interp_v3_v3v3(v1, v1_old, v2_old, 0.5f - fac);
3507  interp_v3_v3v3(v2, v1_old, v2_old, 0.5f + fac);
3508  }
3509 }
3510 
3511 /*
3512  * x1,y2
3513  * | \
3514  * | \ .(a,b)
3515  * | \
3516  * x1,y1-- x2,y1
3517  */
3519  const int x1, const int y1, const int x2, const int y2, const int a, const int b)
3520 {
3521  float v1[2], v2[2], v3[2], p[2];
3522 
3523  v1[0] = (float)x1;
3524  v1[1] = (float)y1;
3525 
3526  v2[0] = (float)x1;
3527  v2[1] = (float)y2;
3528 
3529  v3[0] = (float)x2;
3530  v3[1] = (float)y1;
3531 
3532  p[0] = (float)a;
3533  p[1] = (float)b;
3534 
3535  return isect_point_tri_v2(p, v1, v2, v3);
3536 }
3537 
3538 static bool point_in_slice(const float p[3],
3539  const float v1[3],
3540  const float l1[3],
3541  const float l2[3])
3542 {
3543  /*
3544  * what is a slice ?
3545  * some maths:
3546  * a line including (l1, l2) and a point not on the line
3547  * define a subset of R3 delimited by planes parallel to the line and orthogonal
3548  * to the (point --> line) distance vector, one plane on the line one on the point,
3549  * the room inside usually is rather small compared to R3 though still infinite
3550  * useful for restricting (speeding up) searches
3551  * e.g. all points of triangular prism are within the intersection of 3 'slices'
3552  * another trivial case : cube
3553  * but see a 'spat' which is a deformed cube with paired parallel planes needs only 3 slices too
3554  */
3555  float h, rp[3], cp[3], q[3];
3556 
3557  closest_to_line_v3(cp, v1, l1, l2);
3558  sub_v3_v3v3(q, cp, v1);
3559 
3560  sub_v3_v3v3(rp, p, v1);
3561  h = dot_v3v3(q, rp) / dot_v3v3(q, q);
3562  /* note: when 'h' is nan/-nan, this check returns false
3563  * without explicit check - covering the degenerate case */
3564  return (h >= 0.0f && h <= 1.0f);
3565 }
3566 
3567 /* adult sister defining the slice planes by the origin and the normal
3568  * NOTE |normal| may not be 1 but defining the thickness of the slice */
3569 static bool point_in_slice_as(const float p[3], const float origin[3], const float normal[3])
3570 {
3571  float h, rp[3];
3572  sub_v3_v3v3(rp, p, origin);
3573  h = dot_v3v3(normal, rp) / dot_v3v3(normal, normal);
3574  if (h < 0.0f || h > 1.0f) {
3575  return false;
3576  }
3577  return true;
3578 }
3579 
3580 bool point_in_slice_seg(float p[3], float l1[3], float l2[3])
3581 {
3582  float normal[3];
3583 
3584  sub_v3_v3v3(normal, l2, l1);
3585 
3586  return point_in_slice_as(p, l1, normal);
3587 }
3588 
3589 bool isect_point_tri_prism_v3(const float p[3],
3590  const float v1[3],
3591  const float v2[3],
3592  const float v3[3])
3593 {
3594  if (!point_in_slice(p, v1, v2, v3)) {
3595  return false;
3596  }
3597  if (!point_in_slice(p, v2, v3, v1)) {
3598  return false;
3599  }
3600  if (!point_in_slice(p, v3, v1, v2)) {
3601  return false;
3602  }
3603  return true;
3604 }
3605 
3613  const float p[3], const float v1[3], const float v2[3], const float v3[3], float r_isect_co[3])
3614 {
3615  if (isect_point_tri_prism_v3(p, v1, v2, v3)) {
3616  float plane[4];
3617  float no[3];
3618 
3619  /* Could use normal_tri_v3, but doesn't have to be unit-length */
3620  cross_tri_v3(no, v1, v2, v3);
3621  BLI_assert(len_squared_v3(no) != 0.0f);
3622 
3623  plane_from_point_normal_v3(plane, v1, no);
3624  closest_to_plane_v3(r_isect_co, plane, p);
3625 
3626  return true;
3627  }
3628 
3629  return false;
3630 }
3631 
3633  const float p1[3], const float p2[3], const float plane[4], float r_p1[3], float r_p2[3])
3634 {
3635  float dp[3], div;
3636 
3637  sub_v3_v3v3(dp, p2, p1);
3638  div = dot_v3v3(dp, plane);
3639 
3640  if (div == 0.0f) {
3641  /* parallel */
3642  return true;
3643  }
3644 
3645  float t = -plane_point_side_v3(plane, p1);
3646 
3647  if (div > 0.0f) {
3648  /* behind plane, completely clipped */
3649  if (t >= div) {
3650  return false;
3651  }
3652  if (t > 0.0f) {
3653  const float p1_copy[3] = {UNPACK3(p1)};
3654  copy_v3_v3(r_p2, p2);
3655  madd_v3_v3v3fl(r_p1, p1_copy, dp, t / div);
3656  return true;
3657  }
3658  }
3659  else {
3660  /* behind plane, completely clipped */
3661  if (t >= 0.0f) {
3662  return false;
3663  }
3664  if (t > div) {
3665  const float p1_copy[3] = {UNPACK3(p1)};
3666  copy_v3_v3(r_p1, p1);
3667  madd_v3_v3v3fl(r_p2, p1_copy, dp, t / div);
3668  return true;
3669  }
3670  }
3671 
3672  /* In case input/output values match (above also). */
3673  const float p1_copy[3] = {UNPACK3(p1)};
3674  copy_v3_v3(r_p2, p2);
3675  copy_v3_v3(r_p1, p1_copy);
3676  return true;
3677 }
3678 
3679 bool clip_segment_v3_plane_n(const float p1[3],
3680  const float p2[3],
3681  const float plane_array[][4],
3682  const int plane_tot,
3683  float r_p1[3],
3684  float r_p2[3])
3685 {
3686  /* intersect from both directions */
3687  float p1_fac = 0.0f, p2_fac = 1.0f;
3688 
3689  float dp[3];
3690  sub_v3_v3v3(dp, p2, p1);
3691 
3692  for (int i = 0; i < plane_tot; i++) {
3693  const float *plane = plane_array[i];
3694  const float div = dot_v3v3(dp, plane);
3695 
3696  if (div != 0.0f) {
3697  float t = -plane_point_side_v3(plane, p1);
3698  if (div > 0.0f) {
3699  /* clip p1 lower bounds */
3700  if (t >= div) {
3701  return false;
3702  }
3703  if (t > 0.0f) {
3704  t /= div;
3705  if (t > p1_fac) {
3706  p1_fac = t;
3707  if (p1_fac > p2_fac) {
3708  return false;
3709  }
3710  }
3711  }
3712  }
3713  else if (div < 0.0f) {
3714  /* clip p2 upper bounds */
3715  if (t >= 0.0f) {
3716  return false;
3717  }
3718  if (t > div) {
3719  t /= div;
3720  if (t < p2_fac) {
3721  p2_fac = t;
3722  if (p1_fac > p2_fac) {
3723  return false;
3724  }
3725  }
3726  }
3727  }
3728  }
3729  }
3730 
3731  /* In case input/output values match. */
3732  const float p1_copy[3] = {UNPACK3(p1)};
3733 
3734  madd_v3_v3v3fl(r_p1, p1_copy, dp, p1_fac);
3735  madd_v3_v3v3fl(r_p2, p1_copy, dp, p2_fac);
3736 
3737  return true;
3738 }
3739 
3740 /****************************** Axis Utils ********************************/
3741 
3752 void axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3])
3753 {
3755 
3756  copy_v3_v3(r_mat[2], normal);
3757  ortho_basis_v3v3_v3(r_mat[0], r_mat[1], r_mat[2]);
3758 
3759  BLI_ASSERT_UNIT_V3(r_mat[0]);
3760  BLI_ASSERT_UNIT_V3(r_mat[1]);
3761 
3762  transpose_m3(r_mat);
3763 
3764  BLI_assert(!is_negative_m3(r_mat));
3766  is_zero_v3(normal));
3767 }
3768 
3772 void axis_dominant_v3_to_m3_negate(float r_mat[3][3], const float normal[3])
3773 {
3775 
3776  negate_v3_v3(r_mat[2], normal);
3777  ortho_basis_v3v3_v3(r_mat[0], r_mat[1], r_mat[2]);
3778 
3779  BLI_ASSERT_UNIT_V3(r_mat[0]);
3780  BLI_ASSERT_UNIT_V3(r_mat[1]);
3781 
3782  transpose_m3(r_mat);
3783 
3784  BLI_assert(!is_negative_m3(r_mat));
3786 }
3787 
3788 /****************************** Interpolation ********************************/
3789 
3790 static float tri_signed_area(
3791  const float v1[3], const float v2[3], const float v3[3], const int i, const int j)
3792 {
3793  return 0.5f * ((v1[i] - v2[i]) * (v2[j] - v3[j]) + (v1[j] - v2[j]) * (v3[i] - v2[i]));
3794 }
3795 
3799 static bool barycentric_weights(const float v1[3],
3800  const float v2[3],
3801  const float v3[3],
3802  const float co[3],
3803  const float n[3],
3804  float w[3])
3805 {
3806  float wtot;
3807  int i, j;
3808 
3809  axis_dominant_v3(&i, &j, n);
3810 
3811  w[0] = tri_signed_area(v2, v3, co, i, j);
3812  w[1] = tri_signed_area(v3, v1, co, i, j);
3813  w[2] = tri_signed_area(v1, v2, co, i, j);
3814 
3815  wtot = w[0] + w[1] + w[2];
3816 
3817 #ifdef DEBUG /* Avoid floating point exception when debugging. */
3818  if (wtot != 0.0f)
3819 #endif
3820  {
3821  mul_v3_fl(w, 1.0f / wtot);
3822  if (is_finite_v3(w)) {
3823  return true;
3824  }
3825  }
3826  /* Zero area triangle. */
3827  copy_v3_fl(w, 1.0f / 3.0f);
3828  return false;
3829 }
3830 
3832  float w[3], const float v1[3], const float v2[3], const float v3[3], const float co[3])
3833 {
3834  float n[3];
3835 
3836  normal_tri_v3(n, v1, v2, v3);
3837  barycentric_weights(v1, v2, v3, co, n, w);
3838 }
3839 
3841  const float v1[3],
3842  const float v2[3],
3843  const float v3[3],
3844  const float v4[3],
3845  const float co[3])
3846 {
3847  float w2[3];
3848 
3849  zero_v4(w);
3850 
3851  /* first check for exact match */
3852  if (equals_v3v3(co, v1)) {
3853  w[0] = 1.0f;
3854  }
3855  else if (equals_v3v3(co, v2)) {
3856  w[1] = 1.0f;
3857  }
3858  else if (equals_v3v3(co, v3)) {
3859  w[2] = 1.0f;
3860  }
3861  else if (equals_v3v3(co, v4)) {
3862  w[3] = 1.0f;
3863  }
3864  else {
3865  /* otherwise compute barycentric interpolation weights */
3866  float n1[3], n2[3], n[3];
3867  bool ok;
3868 
3869  sub_v3_v3v3(n1, v1, v3);
3870  sub_v3_v3v3(n2, v2, v4);
3871  cross_v3_v3v3(n, n1, n2);
3872 
3873  ok = barycentric_weights(v1, v2, v4, co, n, w);
3874  SWAP(float, w[2], w[3]);
3875 
3876  if (!ok || (w[0] < 0.0f)) {
3877  /* if w[1] is negative, co is on the other side of the v1-v3 edge,
3878  * so we interpolate using the other triangle */
3879  ok = barycentric_weights(v2, v3, v4, co, n, w2);
3880 
3881  if (ok) {
3882  w[0] = 0.0f;
3883  w[1] = w2[0];
3884  w[2] = w2[1];
3885  w[3] = w2[2];
3886  }
3887  }
3888  }
3889 }
3890 
3898 {
3899  if (IN_RANGE(w[0], 0.0f, 1.0f) && IN_RANGE(w[1], 0.0f, 1.0f) && IN_RANGE(w[2], 0.0f, 1.0f)) {
3900  return 1;
3901  }
3902  if (IN_RANGE_INCL(w[0], 0.0f, 1.0f) && IN_RANGE_INCL(w[1], 0.0f, 1.0f) &&
3903  IN_RANGE_INCL(w[2], 0.0f, 1.0f)) {
3904  return 2;
3905  }
3906 
3907  return 0;
3908 }
3909 
3914  const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3])
3915 {
3916  const float x = co[0], y = co[1];
3917  const float x1 = v1[0], y1 = v1[1];
3918  const float x2 = v2[0], y2 = v2[1];
3919  const float x3 = v3[0], y3 = v3[1];
3920  const float det = (y2 - y3) * (x1 - x3) + (x3 - x2) * (y1 - y3);
3921 
3922 #ifdef DEBUG /* Avoid floating point exception when debugging. */
3923  if (det != 0.0f)
3924 #endif
3925  {
3926  w[0] = ((y2 - y3) * (x - x3) + (x3 - x2) * (y - y3)) / det;
3927  w[1] = ((y3 - y1) * (x - x3) + (x1 - x3) * (y - y3)) / det;
3928  w[2] = 1.0f - w[0] - w[1];
3929  if (is_finite_v3(w)) {
3930  return true;
3931  }
3932  }
3933 
3934  return false;
3935 }
3936 
3944  const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3])
3945 {
3946  float wtot;
3947 
3948  w[0] = cross_tri_v2(v2, v3, co);
3949  w[1] = cross_tri_v2(v3, v1, co);
3950  w[2] = cross_tri_v2(v1, v2, co);
3951  wtot = w[0] + w[1] + w[2];
3952 
3953 #ifdef DEBUG /* Avoid floating point exception when debugging. */
3954  if (wtot != 0.0f)
3955 #endif
3956  {
3957  mul_v3_fl(w, 1.0f / wtot);
3958  if (is_finite_v3(w)) {
3959  return;
3960  }
3961  }
3962  /* Dummy values for zero area face. */
3963  copy_v3_fl(w, 1.0f / 3.0f);
3964 }
3965 
3972  const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3])
3973 {
3974  float wtot;
3975 
3976  w[0] = max_ff(cross_tri_v2(v2, v3, co), 0.0f);
3977  w[1] = max_ff(cross_tri_v2(v3, v1, co), 0.0f);
3978  w[2] = max_ff(cross_tri_v2(v1, v2, co), 0.0f);
3979  wtot = w[0] + w[1] + w[2];
3980 
3981 #ifdef DEBUG /* Avoid floating point exception when debugging. */
3982  if (wtot != 0.0f)
3983 #endif
3984  {
3985  mul_v3_fl(w, 1.0f / wtot);
3986  if (is_finite_v3(w)) {
3987  return;
3988  }
3989  }
3990  /* Dummy values for zero area face. */
3991  copy_v3_fl(w, 1.0f / 3.0f);
3992 }
3993 
3999  const float v1[4], const float v2[4], const float v3[4], const float co[2], float w[3])
4000 {
4001  float wtot;
4002 
4003  w[0] = cross_tri_v2(v2, v3, co) / v1[3];
4004  w[1] = cross_tri_v2(v3, v1, co) / v2[3];
4005  w[2] = cross_tri_v2(v1, v2, co) / v3[3];
4006  wtot = w[0] + w[1] + w[2];
4007 
4008 #ifdef DEBUG /* Avoid floating point exception when debugging. */
4009  if (wtot != 0.0f)
4010 #endif
4011  {
4012  mul_v3_fl(w, 1.0f / wtot);
4013  if (is_finite_v3(w)) {
4014  return;
4015  }
4016  }
4017  /* Dummy values for zero area face. */
4018  copy_v3_fl(w, 1.0f / 3.0f);
4019 }
4020 
4026 void barycentric_weights_v2_quad(const float v1[2],
4027  const float v2[2],
4028  const float v3[2],
4029  const float v4[2],
4030  const float co[2],
4031  float w[4])
4032 {
4033  /* note: fabsf() here is not needed for convex quads (and not used in interp_weights_poly_v2).
4034  * but in the case of concave/bow-tie quads for the mask rasterizer it gives unreliable results
4035  * without adding absf(). If this becomes an issue for more general usage we could have
4036  * this optional or use a different function - Campbell */
4037 #define MEAN_VALUE_HALF_TAN_V2(_area, i1, i2) \
4038  ((_area = cross_v2v2(dirs[i1], dirs[i2])) != 0.0f ? \
4039  fabsf(((lens[i1] * lens[i2]) - dot_v2v2(dirs[i1], dirs[i2])) / _area) : \
4040  0.0f)
4041 
4042  const float dirs[4][2] = {
4043  {v1[0] - co[0], v1[1] - co[1]},
4044  {v2[0] - co[0], v2[1] - co[1]},
4045  {v3[0] - co[0], v3[1] - co[1]},
4046  {v4[0] - co[0], v4[1] - co[1]},
4047  };
4048 
4049  const float lens[4] = {
4050  len_v2(dirs[0]),
4051  len_v2(dirs[1]),
4052  len_v2(dirs[2]),
4053  len_v2(dirs[3]),
4054  };
4055 
4056  /* avoid divide by zero */
4057  if (UNLIKELY(lens[0] < FLT_EPSILON)) {
4058  w[0] = 1.0f;
4059  w[1] = w[2] = w[3] = 0.0f;
4060  }
4061  else if (UNLIKELY(lens[1] < FLT_EPSILON)) {
4062  w[1] = 1.0f;
4063  w[0] = w[2] = w[3] = 0.0f;
4064  }
4065  else if (UNLIKELY(lens[2] < FLT_EPSILON)) {
4066  w[2] = 1.0f;
4067  w[0] = w[1] = w[3] = 0.0f;
4068  }
4069  else if (UNLIKELY(lens[3] < FLT_EPSILON)) {
4070  w[3] = 1.0f;
4071  w[0] = w[1] = w[2] = 0.0f;
4072  }
4073  else {
4074  float wtot, area;
4075 
4076  /* variable 'area' is just for storage,
4077  * the order its initialized doesn't matter */
4078 #ifdef __clang__
4079 # pragma clang diagnostic push
4080 # pragma clang diagnostic ignored "-Wunsequenced"
4081 #endif
4082 
4083  /* inline mean_value_half_tan four times here */
4084  const float t[4] = {
4089  };
4090 
4091 #ifdef __clang__
4092 # pragma clang diagnostic pop
4093 #endif
4094 
4095 #undef MEAN_VALUE_HALF_TAN_V2
4096 
4097  w[0] = (t[3] + t[0]) / lens[0];
4098  w[1] = (t[0] + t[1]) / lens[1];
4099  w[2] = (t[1] + t[2]) / lens[2];
4100  w[3] = (t[2] + t[3]) / lens[3];
4101 
4102  wtot = w[0] + w[1] + w[2] + w[3];
4103 
4104 #ifdef DEBUG /* Avoid floating point exception when debugging. */
4105  if (wtot != 0.0f)
4106 #endif
4107  {
4108  mul_v4_fl(w, 1.0f / wtot);
4109  if (is_finite_v4(w)) {
4110  return;
4111  }
4112  }
4113  /* Dummy values for zero area face. */
4114  copy_v4_fl(w, 1.0f / 4.0f);
4115  }
4116 }
4117 
4118 /* given 2 triangles in 3D space, and a point in relation to the first triangle.
4119  * calculate the location of a point in relation to the second triangle.
4120  * Useful for finding relative positions with geometry */
4121 void transform_point_by_tri_v3(float pt_tar[3],
4122  float const pt_src[3],
4123  const float tri_tar_p1[3],
4124  const float tri_tar_p2[3],
4125  const float tri_tar_p3[3],
4126  const float tri_src_p1[3],
4127  const float tri_src_p2[3],
4128  const float tri_src_p3[3])
4129 {
4130  /* this works by moving the source triangle so its normal is pointing on the Z
4131  * axis where its barycentric weights can be calculated in 2D and its Z offset can
4132  * be re-applied. The weights are applied directly to the targets 3D points and the
4133  * z-depth is used to scale the targets normal as an offset.
4134  * This saves transforming the target into its Z-Up orientation and back
4135  * (which could also work) */
4136  float no_tar[3], no_src[3];
4137  float mat_src[3][3];
4138  float pt_src_xy[3];
4139  float tri_xy_src[3][3];
4140  float w_src[3];
4141  float area_tar, area_src;
4142  float z_ofs_src;
4143 
4144  normal_tri_v3(no_tar, tri_tar_p1, tri_tar_p2, tri_tar_p3);
4145  normal_tri_v3(no_src, tri_src_p1, tri_src_p2, tri_src_p3);
4146 
4147  axis_dominant_v3_to_m3(mat_src, no_src);
4148 
4149  /* make the source tri xy space */
4150  mul_v3_m3v3(pt_src_xy, mat_src, pt_src);
4151  mul_v3_m3v3(tri_xy_src[0], mat_src, tri_src_p1);
4152  mul_v3_m3v3(tri_xy_src[1], mat_src, tri_src_p2);
4153  mul_v3_m3v3(tri_xy_src[2], mat_src, tri_src_p3);
4154 
4155  barycentric_weights_v2(tri_xy_src[0], tri_xy_src[1], tri_xy_src[2], pt_src_xy, w_src);
4156  interp_v3_v3v3v3(pt_tar, tri_tar_p1, tri_tar_p2, tri_tar_p3, w_src);
4157 
4158  area_tar = sqrtf(area_tri_v3(tri_tar_p1, tri_tar_p2, tri_tar_p3));
4159  area_src = sqrtf(area_tri_v2(tri_xy_src[0], tri_xy_src[1], tri_xy_src[2]));
4160 
4161  z_ofs_src = pt_src_xy[2] - tri_xy_src[0][2];
4162  madd_v3_v3v3fl(pt_tar, pt_tar, no_tar, (z_ofs_src / area_src) * area_tar);
4163 }
4164 
4169 void transform_point_by_seg_v3(float p_dst[3],
4170  const float p_src[3],
4171  const float l_dst_p1[3],
4172  const float l_dst_p2[3],
4173  const float l_src_p1[3],
4174  const float l_src_p2[3])
4175 {
4176  float t = line_point_factor_v3(p_src, l_src_p1, l_src_p2);
4177  interp_v3_v3v3(p_dst, l_dst_p1, l_dst_p2, t);
4178 }
4179 
4180 /* given an array with some invalid values this function interpolates valid values
4181  * replacing the invalid ones */
4182 int interp_sparse_array(float *array, const int list_size, const float skipval)
4183 {
4184  int found_invalid = 0;
4185  int found_valid = 0;
4186  int i;
4187 
4188  for (i = 0; i < list_size; i++) {
4189  if (array[i] == skipval) {
4190  found_invalid = 1;
4191  }
4192  else {
4193  found_valid = 1;
4194  }
4195  }
4196 
4197  if (found_valid == 0) {
4198  return -1;
4199  }
4200  if (found_invalid == 0) {
4201  return 0;
4202  }
4203 
4204  /* found invalid depths, interpolate */
4205  float valid_last = skipval;
4206  int valid_ofs = 0;
4207 
4208  float *array_up = MEM_callocN(sizeof(float) * (size_t)list_size, "interp_sparse_array up");
4209  float *array_down = MEM_callocN(sizeof(float) * (size_t)list_size, "interp_sparse_array up");
4210 
4211  int *ofs_tot_up = MEM_callocN(sizeof(int) * (size_t)list_size, "interp_sparse_array tup");
4212  int *ofs_tot_down = MEM_callocN(sizeof(int) * (size_t)list_size, "interp_sparse_array tdown");
4213 
4214  for (i = 0; i < list_size; i++) {
4215  if (array[i] == skipval) {
4216  array_up[i] = valid_last;
4217  ofs_tot_up[i] = ++valid_ofs;
4218  }
4219  else {
4220  valid_last = array[i];
4221  valid_ofs = 0;
4222  }
4223  }
4224 
4225  valid_last = skipval;
4226  valid_ofs = 0;
4227 
4228  for (i = list_size - 1; i >= 0; i--) {
4229  if (array[i] == skipval) {
4230  array_down[i] = valid_last;
4231  ofs_tot_down[i] = ++valid_ofs;
4232  }
4233  else {
4234  valid_last = array[i];
4235  valid_ofs = 0;
4236  }
4237  }
4238 
4239  /* now blend */
4240  for (i = 0; i < list_size; i++) {
4241  if (array[i] == skipval) {
4242  if (array_up[i] != skipval && array_down[i] != skipval) {
4243  array[i] = ((array_up[i] * (float)ofs_tot_down[i]) +
4244  (array_down[i] * (float)ofs_tot_up[i])) /
4245  (float)(ofs_tot_down[i] + ofs_tot_up[i]);
4246  }
4247  else if (array_up[i] != skipval) {
4248  array[i] = array_up[i];
4249  }
4250  else if (array_down[i] != skipval) {
4251  array[i] = array_down[i];
4252  }
4253  }
4254  }
4255 
4256  MEM_freeN(array_up);
4257  MEM_freeN(array_down);
4258 
4259  MEM_freeN(ofs_tot_up);
4260  MEM_freeN(ofs_tot_down);
4261 
4262  return 1;
4263 }
4264 
4265 /* -------------------------------------------------------------------- */
4269 #define IS_POINT_IX (1 << 0)
4270 #define IS_SEGMENT_IX (1 << 1)
4271 
4272 #define DIR_V3_SET(d_len, va, vb) \
4273  { \
4274  sub_v3_v3v3((d_len)->dir, va, vb); \
4275  (d_len)->len = len_v3((d_len)->dir); \
4276  } \
4277  (void)0
4278 
4279 #define DIR_V2_SET(d_len, va, vb) \
4280  { \
4281  sub_v2db_v2fl_v2fl((d_len)->dir, va, vb); \
4282  (d_len)->len = len_v2_db((d_len)->dir); \
4283  } \
4284  (void)0
4285 
4286 struct Float3_Len {
4287  float dir[3], len;
4288 };
4289 
4290 struct Double2_Len {
4291  double dir[2], len;
4292 };
4293 
4294 /* Mean value weights - smooth interpolation weights for polygons with
4295  * more than 3 vertices */
4296 static float mean_value_half_tan_v3(const struct Float3_Len *d_curr,
4297  const struct Float3_Len *d_next)
4298 {
4299  float cross[3];
4300  cross_v3_v3v3(cross, d_curr->dir, d_next->dir);
4301  const float area = len_v3(cross);
4302  /* Compare against zero since 'FLT_EPSILON' can be too large, see: T73348. */
4303  if (LIKELY(area != 0.0f)) {
4304  const float dot = dot_v3v3(d_curr->dir, d_next->dir);
4305  const float len = d_curr->len * d_next->len;
4306  const float result = (len - dot) / area;
4307  if (isfinite(result)) {
4308  return result;
4309  }
4310  }
4311  return 0.0f;
4312 }
4313 
4323 static double mean_value_half_tan_v2_db(const struct Double2_Len *d_curr,
4324  const struct Double2_Len *d_next)
4325 {
4326  /* Different from the 3d version but still correct. */
4327  const double area = cross_v2v2_db(d_curr->dir, d_next->dir);
4328  /* Compare against zero since 'FLT_EPSILON' can be too large, see: T73348. */
4329  if (LIKELY(area != 0.0)) {
4330  const double dot = dot_v2v2_db(d_curr->dir, d_next->dir);
4331  const double len = d_curr->len * d_next->len;
4332  const double result = (len - dot) / area;
4333  if (isfinite(result)) {
4334  return result;
4335  }
4336  }
4337  return 0.0;
4338 }
4339 
4340 void interp_weights_poly_v3(float *w, float v[][3], const int n, const float co[3])
4341 {
4342  /* Before starting to calculate the weight, we need to figure out the floating point precision we
4343  * can expect from the supplied data. */
4344  float max_value = 0;
4345 
4346  for (int i = 0; i < n; i++) {
4347  max_value = max_ff(max_value, fabsf(v[i][0] - co[0]));
4348  max_value = max_ff(max_value, fabsf(v[i][1] - co[1]));
4349  max_value = max_ff(max_value, fabsf(v[i][2] - co[2]));
4350  }
4351 
4352  /* These to values we derived by empirically testing different values that works for the test
4353  * files in D7772. */
4354  const float eps = 16.0f * FLT_EPSILON * max_value;
4355  const float eps_sq = eps * eps;
4356  const float *v_curr, *v_next;
4357  float ht_prev, ht; /* half tangents */
4358  float totweight = 0.0f;
4359  int i_curr, i_next;
4360  char ix_flag = 0;
4361  struct Float3_Len d_curr, d_next;
4362 
4363  /* loop over 'i_next' */
4364  i_curr = n - 1;
4365  i_next = 0;
4366 
4367  v_curr = v[i_curr];
4368  v_next = v[i_next];
4369 
4370  DIR_V3_SET(&d_curr, v_curr - 3 /* v[n - 2] */, co);
4371  DIR_V3_SET(&d_next, v_curr /* v[n - 1] */, co);
4372  ht_prev = mean_value_half_tan_v3(&d_curr, &d_next);
4373 
4374  while (i_next < n) {
4375  /* Mark Mayer et al algorithm that is used here does not operate well if vertex is close
4376  * to borders of face.
4377  * In that case, do simple linear interpolation between the two edge vertices */
4378 
4379  /* 'd_next.len' is in fact 'd_curr.len', just avoid copy to begin with */
4380  if (UNLIKELY(d_next.len < eps)) {
4381  ix_flag = IS_POINT_IX;
4382  break;
4383  }
4384  if (UNLIKELY(dist_squared_to_line_segment_v3(co, v_curr, v_next) < eps_sq)) {
4385  ix_flag = IS_SEGMENT_IX;
4386  break;
4387  }
4388 
4389  d_curr = d_next;
4390  DIR_V3_SET(&d_next, v_next, co);
4391  ht = mean_value_half_tan_v3(&d_curr, &d_next);
4392  w[i_curr] = (ht_prev + ht) / d_curr.len;
4393  totweight += w[i_curr];
4394 
4395  /* step */
4396  i_curr = i_next++;
4397  v_curr = v_next;
4398  v_next = v[i_next];
4399 
4400  ht_prev = ht;
4401  }
4402 
4403  if (ix_flag) {
4404  memset(w, 0, sizeof(*w) * (size_t)n);
4405 
4406  if (ix_flag & IS_POINT_IX) {
4407  w[i_curr] = 1.0f;
4408  }
4409  else {
4410  float fac = line_point_factor_v3(co, v_curr, v_next);
4411  CLAMP(fac, 0.0f, 1.0f);
4412  w[i_curr] = 1.0f - fac;
4413  w[i_next] = fac;
4414  }
4415  }
4416  else {
4417  if (totweight != 0.0f) {
4418  for (i_curr = 0; i_curr < n; i_curr++) {
4419  w[i_curr] /= totweight;
4420  }
4421  }
4422  }
4423 }
4424 
4425 void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[2])
4426 {
4427  /* Before starting to calculate the weight, we need to figure out the floating point precision we
4428  * can expect from the supplied data. */
4429  float max_value = 0;
4430 
4431  for (int i = 0; i < n; i++) {
4432  max_value = max_ff(max_value, fabsf(v[i][0] - co[0]));
4433  max_value = max_ff(max_value, fabsf(v[i][1] - co[1]));
4434  }
4435 
4436  /* These to values we derived by empirically testing different values that works for the test
4437  * files in D7772. */
4438  const float eps = 16.0f * FLT_EPSILON * max_value;
4439  const float eps_sq = eps * eps;
4440 
4441  const float *v_curr, *v_next;
4442  double ht_prev, ht; /* half tangents */
4443  float totweight = 0.0f;
4444  int i_curr, i_next;
4445  char ix_flag = 0;
4446  struct Double2_Len d_curr, d_next;
4447 
4448  /* loop over 'i_next' */
4449  i_curr = n - 1;
4450  i_next = 0;
4451 
4452  v_curr = v[i_curr];
4453  v_next = v[i_next];
4454 
4455  DIR_V2_SET(&d_curr, v_curr - 2 /* v[n - 2] */, co);
4456  DIR_V2_SET(&d_next, v_curr /* v[n - 1] */, co);
4457  ht_prev = mean_value_half_tan_v2_db(&d_curr, &d_next);
4458 
4459  while (i_next < n) {
4460  /* Mark Mayer et al algorithm that is used here does not operate well if vertex is close
4461  * to borders of face. In that case,
4462  * do simple linear interpolation between the two edge vertices */
4463 
4464  /* 'd_next.len' is in fact 'd_curr.len', just avoid copy to begin with */
4465  if (UNLIKELY(d_next.len < eps)) {
4466  ix_flag = IS_POINT_IX;
4467  break;
4468  }
4469  if (UNLIKELY(dist_squared_to_line_segment_v2(co, v_curr, v_next) < eps_sq)) {
4470  ix_flag = IS_SEGMENT_IX;
4471  break;
4472  }
4473 
4474  d_curr = d_next;
4475  DIR_V2_SET(&d_next, v_next, co);
4476  ht = mean_value_half_tan_v2_db(&d_curr, &d_next);
4477  w[i_curr] = (d_curr.len == 0.0) ? 0.0f : (float)((ht_prev + ht) / d_curr.len);
4478  totweight += w[i_curr];
4479 
4480  /* step */
4481  i_curr = i_next++;
4482  v_curr = v_next;
4483  v_next = v[i_next];
4484 
4485  ht_prev = ht;
4486  }
4487 
4488  if (ix_flag) {
4489  memset(w, 0, sizeof(*w) * (size_t)n);
4490 
4491  if (ix_flag & IS_POINT_IX) {
4492  w[i_curr] = 1.0f;
4493  }
4494  else {
4495  float fac = line_point_factor_v2(co, v_curr, v_next);
4496  CLAMP(fac, 0.0f, 1.0f);
4497  w[i_curr] = 1.0f - fac;
4498  w[i_next] = fac;
4499  }
4500  }
4501  else {
4502  if (totweight != 0.0f) {
4503  for (i_curr = 0; i_curr < n; i_curr++) {
4504  w[i_curr] /= totweight;
4505  }
4506  }
4507  }
4508 }
4509 
4510 #undef IS_POINT_IX
4511 #undef IS_SEGMENT_IX
4512 
4513 #undef DIR_V3_SET
4514 #undef DIR_V2_SET
4515 
4518 /* (x1, v1)(t1=0)------(x2, v2)(t2=1), 0<t<1 --> (x, v)(t) */
4519 void interp_cubic_v3(float x[3],
4520  float v[3],
4521  const float x1[3],
4522  const float v1[3],
4523  const float x2[3],
4524  const float v2[3],
4525  const float t)
4526 {
4527  float a[3], b[3];
4528  const float t2 = t * t;
4529  const float t3 = t2 * t;
4530 
4531  /* cubic interpolation */
4532  a[0] = v1[0] + v2[0] + 2 * (x1[0] - x2[0]);
4533  a[1] = v1[1] + v2[1] + 2 * (x1[1] - x2[1]);
4534  a[2] = v1[2] + v2[2] + 2 * (x1[2] - x2[2]);
4535 
4536  b[0] = -2 * v1[0] - v2[0] - 3 * (x1[0] - x2[0]);
4537  b[1] = -2 * v1[1] - v2[1] - 3 * (x1[1] - x2[1]);
4538  b[2] = -2 * v1[2] - v2[2] - 3 * (x1[2] - x2[2]);
4539 
4540  x[0] = a[0] * t3 + b[0] * t2 + v1[0] * t + x1[0];
4541  x[1] = a[1] * t3 + b[1] * t2 + v1[1] * t + x1[1];
4542  x[2] = a[2] * t3 + b[2] * t2 + v1[2] * t + x1[2];
4543 
4544  v[0] = 3 * a[0] * t2 + 2 * b[0] * t + v1[0];
4545  v[1] = 3 * a[1] * t2 + 2 * b[1] * t + v1[1];
4546  v[2] = 3 * a[2] * t2 + 2 * b[2] * t + v1[2];
4547 }
4548 
4549 /* unfortunately internal calculations have to be done at double precision
4550  * to achieve correct/stable results. */
4551 
4552 #define IS_ZERO(x) ((x > (-DBL_EPSILON) && x < DBL_EPSILON) ? 1 : 0)
4553 
4562  float r_uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2])
4563 {
4564  /* find UV such that
4565  * t = u * t0 + v * t1 + (1 - u - v) * t2
4566  * u * (t0 - t2) + v * (t1 - t2) = t - t2 */
4567  const double a = st0[0] - st2[0], b = st1[0] - st2[0];
4568  const double c = st0[1] - st2[1], d = st1[1] - st2[1];
4569  const double det = a * d - c * b;
4570 
4571  /* det should never be zero since the determinant is the signed ST area of the triangle. */
4572  if (IS_ZERO(det) == 0) {
4573  const double x[2] = {st[0] - st2[0], st[1] - st2[1]};
4574 
4575  r_uv[0] = (float)((d * x[0] - b * x[1]) / det);
4576  r_uv[1] = (float)(((-c) * x[0] + a * x[1]) / det);
4577  }
4578  else {
4579  zero_v2(r_uv);
4580  }
4581 }
4582 
4589  float r_uv[2], const float st[3], const float st0[3], const float st1[3], const float st2[3])
4590 {
4591  float v0[3], v1[3], v2[3];
4592  double d00, d01, d11, d20, d21, det;
4593 
4594  sub_v3_v3v3(v0, st1, st0);
4595  sub_v3_v3v3(v1, st2, st0);
4596  sub_v3_v3v3(v2, st, st0);
4597 
4598  d00 = dot_v3v3(v0, v0);
4599  d01 = dot_v3v3(v0, v1);
4600  d11 = dot_v3v3(v1, v1);
4601  d20 = dot_v3v3(v2, v0);
4602  d21 = dot_v3v3(v2, v1);
4603 
4604  det = d00 * d11 - d01 * d01;
4605 
4606  /* det should never be zero since the determinant is the signed ST area of the triangle. */
4607  if (IS_ZERO(det) == 0) {
4608  float w;
4609 
4610  w = (float)((d00 * d21 - d01 * d20) / det);
4611  r_uv[1] = (float)((d11 * d20 - d01 * d21) / det);
4612  r_uv[0] = 1.0f - r_uv[1] - w;
4613  }
4614  else {
4615  zero_v2(r_uv);
4616  }
4617 }
4618 
4619 /* bilinear reverse */
4620 void resolve_quad_uv_v2(float r_uv[2],
4621  const float st[2],
4622  const float st0[2],
4623  const float st1[2],
4624  const float st2[2],
4625  const float st3[2])
4626 {
4627  resolve_quad_uv_v2_deriv(r_uv, NULL, st, st0, st1, st2, st3);
4628 }
4629 
4630 /* bilinear reverse with derivatives */
4631 void resolve_quad_uv_v2_deriv(float r_uv[2],
4632  float r_deriv[2][2],
4633  const float st[2],
4634  const float st0[2],
4635  const float st1[2],
4636  const float st2[2],
4637  const float st3[2])
4638 {
4639  const double signed_area = (st0[0] * st1[1] - st0[1] * st1[0]) +
4640  (st1[0] * st2[1] - st1[1] * st2[0]) +
4641  (st2[0] * st3[1] - st2[1] * st3[0]) +
4642  (st3[0] * st0[1] - st3[1] * st0[0]);
4643 
4644  /* X is 2D cross product (determinant)
4645  * A = (p0 - p) X (p0 - p3)*/
4646  const double a = (st0[0] - st[0]) * (st0[1] - st3[1]) - (st0[1] - st[1]) * (st0[0] - st3[0]);
4647 
4648  /* B = ( (p0 - p) X (p1 - p2) + (p1 - p) X (p0 - p3) ) / 2 */
4649  const double b = 0.5 * (double)(((st0[0] - st[0]) * (st1[1] - st2[1]) -
4650  (st0[1] - st[1]) * (st1[0] - st2[0])) +
4651  ((st1[0] - st[0]) * (st0[1] - st3[1]) -
4652  (st1[1] - st[1]) * (st0[0] - st3[0])));
4653 
4654  /* C = (p1-p) X (p1-p2) */
4655  const double fC = (st1[0] - st[0]) * (st1[1] - st2[1]) - (st1[1] - st[1]) * (st1[0] - st2[0]);
4656  double denom = a - 2 * b + fC;
4657 
4658  /* clear outputs */
4659  zero_v2(r_uv);
4660 
4661  if (IS_ZERO(denom) != 0) {
4662  const double fDen = a - fC;
4663  if (IS_ZERO(fDen) == 0) {
4664  r_uv[0] = (float)(a / fDen);
4665  }
4666  }
4667  else {
4668  const double desc_sq = b * b - a * fC;
4669  const double desc = sqrt(desc_sq < 0.0 ? 0.0 : desc_sq);
4670  const double s = signed_area > 0 ? (-1.0) : 1.0;
4671 
4672  r_uv[0] = (float)(((a - b) + s * desc) / denom);
4673  }
4674 
4675  /* find UV such that
4676  * fST = (1-u)(1-v) * ST0 + u * (1-v) * ST1 + u * v * ST2 + (1-u) * v * ST3 */
4677  {
4678  const double denom_s = (1 - r_uv[0]) * (st0[0] - st3[0]) + r_uv[0] * (st1[0] - st2[0]);
4679  const double denom_t = (1 - r_uv[0]) * (st0[1] - st3[1]) + r_uv[0] * (st1[1] - st2[1]);
4680  int i = 0;
4681  denom = denom_s;
4682 
4683  if (fabs(denom_s) < fabs(denom_t)) {
4684  i = 1;
4685  denom = denom_t;
4686  }
4687 
4688  if (IS_ZERO(denom) == 0) {
4689  r_uv[1] = (float)((double)((1.0f - r_uv[0]) * (st0[i] - st[i]) +
4690  r_uv[0] * (st1[i] - st[i])) /
4691  denom);
4692  }
4693  }
4694 
4695  if (r_deriv) {
4696  float tmp1[2], tmp2[2], s[2], t[2];
4697 
4698  /* clear outputs */
4699  zero_v2(r_deriv[0]);
4700  zero_v2(r_deriv[1]);
4701 
4702  sub_v2_v2v2(tmp1, st1, st0);
4703  sub_v2_v2v2(tmp2, st2, st3);
4704  interp_v2_v2v2(s, tmp1, tmp2, r_uv[1]);
4705  sub_v2_v2v2(tmp1, st3, st0);
4706  sub_v2_v2v2(tmp2, st2, st1);
4707  interp_v2_v2v2(t, tmp1, tmp2, r_uv[0]);
4708 
4709  denom = t[0] * s[1] - t[1] * s[0];
4710 
4711  if (!IS_ZERO(denom)) {
4712  double inv_denom = 1.0 / denom;
4713  r_deriv[0][0] = (float)((double)-t[1] * inv_denom);
4714  r_deriv[0][1] = (float)((double)t[0] * inv_denom);
4715  r_deriv[1][0] = (float)((double)s[1] * inv_denom);
4716  r_deriv[1][1] = (float)((double)-s[0] * inv_denom);
4717  }
4718  }
4719 }
4720 
4721 /* a version of resolve_quad_uv_v2 that only calculates the 'u' */
4722 float resolve_quad_u_v2(const float st[2],
4723  const float st0[2],
4724  const float st1[2],
4725  const float st2[2],
4726  const float st3[2])
4727 {
4728  const double signed_area = (st0[0] * st1[1] - st0[1] * st1[0]) +
4729  (st1[0] * st2[1] - st1[1] * st2[0]) +
4730  (st2[0] * st3[1] - st2[1] * st3[0]) +
4731  (st3[0] * st0[1] - st3[1] * st0[0]);
4732 
4733  /* X is 2D cross product (determinant)
4734  * A = (p0 - p) X (p0 - p3)*/
4735  const double a = (st0[0] - st[0]) * (st0[1] - st3[1]) - (st0[1] - st[1]) * (st0[0] - st3[0]);
4736 
4737  /* B = ( (p0 - p) X (p1 - p2) + (p1 - p) X (p0 - p3) ) / 2 */
4738  const double b = 0.5 * (double)(((st0[0] - st[0]) * (st1[1] - st2[1]) -
4739  (st0[1] - st[1]) * (st1[0] - st2[0])) +
4740  ((st1[0] - st[0]) * (st0[1] - st3[1]) -
4741  (st1[1] - st[1]) * (st0[0] - st3[0])));
4742 
4743  /* C = (p1-p) X (p1-p2) */
4744  const double fC = (st1[0] - st[0]) * (st1[1] - st2[1]) - (st1[1] - st[1]) * (st1[0] - st2[0]);
4745  double denom = a - 2 * b + fC;
4746 
4747  if (IS_ZERO(denom) != 0) {
4748  const double fDen = a - fC;
4749  if (IS_ZERO(fDen) == 0) {
4750  return (float)(a / fDen);
4751  }
4752 
4753  return 0.0f;
4754  }
4755 
4756  const double desc_sq = b * b - a * fC;
4757  const double desc = sqrt(desc_sq < 0.0 ? 0.0 : desc_sq);
4758  const double s = signed_area > 0 ? (-1.0) : 1.0;
4759 
4760  return (float)(((a - b) + s * desc) / denom);
4761 }
4762 
4763 #undef IS_ZERO
4764 
4765 /* reverse of the functions above */
4766 void interp_bilinear_quad_v3(float data[4][3], float u, float v, float res[3])
4767 {
4768  float vec[3];
4769 
4770  copy_v3_v3(res, data[0]);
4771  mul_v3_fl(res, (1 - u) * (1 - v));
4772  copy_v3_v3(vec, data[1]);
4773  mul_v3_fl(vec, u * (1 - v));
4774  add_v3_v3(res, vec);
4775  copy_v3_v3(vec, data[2]);
4776  mul_v3_fl(vec, u * v);
4777  add_v3_v3(res, vec);
4778  copy_v3_v3(vec, data[3]);
4779  mul_v3_fl(vec, (1 - u) * v);
4780  add_v3_v3(res, vec);
4781 }
4782 
4783 void interp_barycentric_tri_v3(float data[3][3], float u, float v, float res[3])
4784 {
4785  float vec[3];
4786 
4787  copy_v3_v3(res, data[0]);
4788  mul_v3_fl(res, u);
4789  copy_v3_v3(vec, data[1]);
4790  mul_v3_fl(vec, v);
4791  add_v3_v3(res, vec);
4792  copy_v3_v3(vec, data[2]);
4793  mul_v3_fl(vec, 1.0f - u - v);
4794  add_v3_v3(res, vec);
4795 }
4796 
4797 /***************************** View & Projection *****************************/
4798 
4802 void orthographic_m4(float matrix[4][4],
4803  const float left,
4804  const float right,
4805  const float bottom,
4806  const float top,
4807  const float nearClip,
4808  const float farClip)
4809 {
4810  float Xdelta, Ydelta, Zdelta;
4811 
4812  Xdelta = right - left;
4813  Ydelta = top - bottom;
4814  Zdelta = farClip - nearClip;
4815  if (Xdelta == 0.0f || Ydelta == 0.0f || Zdelta == 0.0f) {
4816  return;
4817  }
4818  unit_m4(matrix);
4819  matrix[0][0] = 2.0f / Xdelta;
4820  matrix[3][0] = -(right + left) / Xdelta;
4821  matrix[1][1] = 2.0f / Ydelta;
4822  matrix[3][1] = -(top + bottom) / Ydelta;
4823  matrix[2][2] = -2.0f / Zdelta; /* note: negate Z */
4824  matrix[3][2] = -(farClip + nearClip) / Zdelta;
4825 }
4826 
4830 void perspective_m4(float mat[4][4],
4831  const float left,
4832  const float right,
4833  const float bottom,
4834  const float top,
4835  const float nearClip,
4836  const float farClip)
4837 {
4838  const float Xdelta = right - left;
4839  const float Ydelta = top - bottom;
4840  const float Zdelta = farClip - nearClip;
4841 
4842  if (Xdelta == 0.0f || Ydelta == 0.0f || Zdelta == 0.0f) {
4843  return;
4844  }
4845  mat[0][0] = nearClip * 2.0f / Xdelta;
4846  mat[1][1] = nearClip * 2.0f / Ydelta;
4847  mat[2][0] = (right + left) / Xdelta; /* note: negate Z */
4848  mat[2][1] = (top + bottom) / Ydelta;
4849  mat[2][2] = -(farClip + nearClip) / Zdelta;
4850  mat[2][3] = -1.0f;
4851  mat[3][2] = (-2.0f * nearClip * farClip) / Zdelta;
4852  mat[0][1] = mat[0][2] = mat[0][3] = mat[1][0] = mat[1][2] = mat[1][3] = mat[3][0] = mat[3][1] =
4853  mat[3][3] = 0.0f;
4854 }
4855 
4856 void perspective_m4_fov(float mat[4][4],
4857  const float angle_left,
4858  const float angle_right,
4859  const float angle_up,
4860  const float angle_down,
4861  const float nearClip,
4862  const float farClip)
4863 {
4864  const float tan_angle_left = tanf(angle_left);
4865  const float tan_angle_right = tanf(angle_right);
4866  const float tan_angle_bottom = tanf(angle_up);
4867  const float tan_angle_top = tanf(angle_down);
4868 
4870  mat, tan_angle_left, tan_angle_right, tan_angle_top, tan_angle_bottom, nearClip, farClip);
4871  mat[0][0] /= nearClip;
4872  mat[1][1] /= nearClip;
4873 }
4874 
4875 /* translate a matrix created by orthographic_m4 or perspective_m4 in XY coords
4876  * (used to jitter the view) */
4877 void window_translate_m4(float winmat[4][4], float perspmat[4][4], const float x, const float y)
4878 {
4879  if (winmat[2][3] == -1.0f) {
4880  /* in the case of a win-matrix, this means perspective always */
4881  float v1[3];
4882  float v2[3];
4883  float len1, len2;
4884 
4885  v1[0] = perspmat[0][0];
4886  v1[1] = perspmat[1][0];
4887  v1[2] = perspmat[2][0];
4888 
4889  v2[0] = perspmat[0][1];
4890  v2[1] = perspmat[1][1];
4891  v2[2] = perspmat[2][1];
4892 
4893  len1 = (1.0f / len_v3(v1));
4894  len2 = (1.0f / len_v3(v2));
4895 
4896  winmat[2][0] -= len1 * winmat[0][0] * x;
4897  winmat[2][1] -= len2 * winmat[1][1] * y;
4898  }
4899  else {
4900  winmat[3][0] += x;
4901  winmat[3][1] += y;
4902  }
4903 }
4904 
4911 void planes_from_projmat(const float mat[4][4],
4912  float left[4],
4913  float right[4],
4914  float top[4],
4915  float bottom[4],
4916  float near[4],
4917  float far[4])
4918 {
4919  /* References:
4920  *
4921  * https://fgiesen.wordpress.com/2012/08/31/frustum-planes-from-the-projection-matrix/
4922  * http://www8.cs.umu.se/kurser/5DV051/HT12/lab/plane_extraction.pdf
4923  */
4924 
4925  int i;
4926 
4927  if (left) {
4928  for (i = 4; i--;) {
4929  left[i] = mat[i][3] + mat[i][0];
4930  }
4931  }
4932 
4933  if (right) {
4934  for (i = 4; i--;) {
4935  right[i] = mat[i][3] - mat[i][0];
4936  }
4937  }
4938 
4939  if (bottom) {
4940  for (i = 4; i--;) {
4941  bottom[i] = mat[i][3] + mat[i][1];
4942  }
4943  }
4944 
4945  if (top) {
4946  for (i = 4; i--;) {
4947  top[i] = mat[i][3] - mat[i][1];
4948  }
4949  }
4950 
4951  if (near) {
4952  for (i = 4; i--;) {
4953  near[i] = mat[i][3] + mat[i][2];
4954  }
4955  }
4956 
4957  if (far) {
4958  for (i = 4; i--;) {
4959  far[i] = mat[i][3] - mat[i][2];
4960  }
4961  }
4962 }
4963 
4964 void projmat_dimensions(const float projmat[4][4],
4965  float *r_left,
4966  float *r_right,
4967  float *r_bottom,
4968  float *r_top,
4969  float *r_near,
4970  float *r_far)
4971 {
4972  bool is_persp = projmat[3][3] == 0.0f;
4973 
4974  if (is_persp) {
4975  *r_left = (projmat[2][0] - 1.0f) / projmat[0][0];
4976  *r_right = (projmat[2][0] + 1.0f) / projmat[0][0];
4977  *r_bottom = (projmat[2][1] - 1.0f) / projmat[1][1];
4978  *r_top = (projmat[2][1] + 1.0f) / projmat[1][1];
4979  *r_near = projmat[3][2] / (projmat[2][2] - 1.0f);
4980  *r_far = projmat[3][2] / (projmat[2][2] + 1.0f);
4981  }
4982  else {
4983  *r_left = (-projmat[3][0] - 1.0f) / projmat[0][0];
4984  *r_right = (-projmat[3][0] + 1.0f) / projmat[0][0];
4985  *r_bottom = (-projmat[3][1] - 1.0f) / projmat[1][1];
4986  *r_top = (-projmat[3][1] + 1.0f) / projmat[1][1];
4987  *r_near = (projmat[3][2] + 1.0f) / projmat[2][2];
4988  *r_far = (projmat[3][2] - 1.0f) / projmat[2][2];
4989  }
4990 }
4991 
4992 void projmat_dimensions_db(const float projmat_fl[4][4],
4993  double *r_left,
4994  double *r_right,
4995  double *r_bottom,
4996  double *r_top,
4997  double *r_near,
4998  double *r_far)
4999 {
5000  double projmat[4][4];
5001  copy_m4d_m4(projmat, projmat_fl);
5002 
5003  bool is_persp = projmat[3][3] == 0.0f;
5004 
5005  if (is_persp) {
5006  *r_left = (projmat[2][0] - 1.0) / projmat[0][0];
5007  *r_right = (projmat[2][0] + 1.0) / projmat[0][0];
5008  *r_bottom = (projmat[2][1] - 1.0) / projmat[1][1];
5009  *r_top = (projmat[2][1] + 1.0) / projmat[1][1];
5010  *r_near = projmat[3][2] / (projmat[2][2] - 1.0);
5011  *r_far = projmat[3][2] / (projmat[2][2] + 1.0);
5012  }
5013  else {
5014  *r_left = (-projmat[3][0] - 1.0) / projmat[0][0];
5015  *r_right = (-projmat[3][0] + 1.0) / projmat[0][0];
5016  *r_bottom = (-projmat[3][1] - 1.0) / projmat[1][1];
5017  *r_top = (-projmat[3][1] + 1.0) / projmat[1][1];
5018  *r_near = (projmat[3][2] + 1.0) / projmat[2][2];
5019  *r_far = (projmat[3][2] - 1.0) / projmat[2][2];
5020  }
5021 }
5022 
5031 void projmat_from_subregion(const float projmat[4][4],
5032  const int win_size[2],
5033  const int x_min,
5034  const int x_max,
5035  const int y_min,
5036  const int y_max,
5037  float r_projmat[4][4])
5038 {
5039  float rect_width = (float)(x_max - x_min);
5040  float rect_height = (float)(y_max - y_min);
5041 
5042  float x_sca = (float)win_size[0] / rect_width;
5043  float y_sca = (float)win_size[1] / rect_height;
5044 
5045  float x_fac = (float)((x_min + x_max) - win_size[0]) / rect_width;
5046  float y_fac = (float)((y_min + y_max) - win_size[1]) / rect_height;
5047 
5048  copy_m4_m4(r_projmat, projmat);
5049  r_projmat[0][0] *= x_sca;
5050  r_projmat[1][1] *= y_sca;
5051 
5052  if (projmat[3][3] == 0.0f) {
5053  r_projmat[2][0] = r_projmat[2][0] * x_sca + x_fac;
5054  r_projmat[2][1] = r_projmat[2][1] * y_sca + y_fac;
5055  }
5056  else {
5057  r_projmat[3][0] = r_projmat[3][0] * x_sca - x_fac;
5058  r_projmat[3][1] = r_projmat[3][1] * y_sca - y_fac;
5059  }
5060 }
5061 
5062 static void i_multmatrix(const float icand[4][4], float mat[4][4])
5063 {
5064  int row, col;
5065  float temp[4][4];
5066 
5067  for (row = 0; row < 4; row++) {
5068  for (col = 0; col < 4; col++) {
5069  temp[row][col] = (icand[row][0] * mat[0][col] + icand[row][1] * mat[1][col] +
5070  icand[row][2] * mat[2][col] + icand[row][3] * mat[3][col]);
5071  }
5072  }
5073  copy_m4_m4(mat, temp);
5074 }
5075 
5076 void polarview_m4(float mat[4][4], float dist, float azimuth, float incidence, float twist)
5077 {
5078  unit_m4(mat);
5079 
5080  translate_m4(mat, 0.0, 0.0, -dist);
5081  rotate_m4(mat, 'Z', -twist);
5082  rotate_m4(mat, 'X', -incidence);
5083  rotate_m4(mat, 'Z', -azimuth);
5084 }
5085 
5087  float mat[4][4], float vx, float vy, float vz, float px, float py, float pz, float twist)
5088 {
5089  float sine, cosine, hyp, hyp1, dx, dy, dz;
5090  float mat1[4][4];
5091 
5092  unit_m4(mat1);
5093 
5094  axis_angle_to_mat4_single(mat, 'Z', -twist);
5095 
5096  dx = px - vx;
5097  dy = py - vy;
5098  dz = pz - vz;
5099  hyp = dx * dx + dz * dz; /* hyp squared */
5100  hyp1 = sqrtf(dy * dy + hyp);
5101  hyp = sqrtf(hyp); /* the real hyp */
5102 
5103  if (hyp1 != 0.0f) { /* rotate X */
5104  sine = -dy / hyp1;
5105  cosine = hyp / hyp1;
5106  }
5107  else {
5108  sine = 0.0f;
5109  cosine = 1.0f;
5110  }
5111  mat1[1][1] = cosine;
5112  mat1[1][2] = sine;
5113  mat1[2][1] = -sine;
5114  mat1[2][2] = cosine;
5115 
5116  i_multmatrix(mat1, mat);
5117 
5118  mat1[1][1] = mat1[2][2] = 1.0f; /* be careful here to reinit */
5119  mat1[1][2] = mat1[2][1] = 0.0f; /* those modified by the last */
5120 
5121  /* paragraph */
5122  if (hyp != 0.0f) { /* rotate Y */
5123  sine = dx / hyp;
5124  cosine = -dz / hyp;
5125  }
5126  else {
5127  sine = 0.0f;
5128  cosine = 1.0f;
5129  }
5130  mat1[0][0] = cosine;
5131  mat1[0][2] = -sine;
5132  mat1[2][0] = sine;
5133  mat1[2][2] = cosine;
5134 
5135  i_multmatrix(mat1, mat);
5136  translate_m4(mat, -vx, -vy, -vz); /* translate viewpoint to origin */
5137 }
5138 
5139 int box_clip_bounds_m4(float boundbox[2][3], const float bounds[4], float winmat[4][4])
5140 {
5141  float mat[4][4], vec[4];
5142  int a, fl, flag = -1;
5143 
5144  copy_m4_m4(mat, winmat);
5145 
5146  for (a = 0; a < 8; a++) {
5147  vec[0] = (a & 1) ? boundbox[0][0] : boundbox[1][0];
5148  vec[1] = (a & 2) ? boundbox[0][1] : boundbox[1][1];
5149  vec[2] = (a & 4) ? boundbox[0][2] : boundbox[1][2];
5150  vec[3] = 1.0;
5151  mul_m4_v4(mat, vec);
5152 
5153  fl = 0;
5154  if (bounds) {
5155  if (vec[0] > bounds[1] * vec[3]) {
5156  fl |= 1;
5157  }
5158  if (vec[0] < bounds[0] * vec[3]) {
5159  fl |= 2;
5160  }
5161  if (vec[1] > bounds[3] * vec[3]) {
5162  fl |= 4;
5163  }
5164  if (vec[1] < bounds[2] * vec[3]) {
5165  fl |= 8;
5166  }
5167  }
5168  else {
5169  if (vec[0] < -vec[3]) {
5170  fl |= 1;
5171  }
5172  if (vec[0] > vec[3]) {
5173  fl |= 2;
5174  }
5175  if (vec[1] < -vec[3]) {
5176  fl |= 4;
5177  }
5178  if (vec[1] > vec[3]) {
5179  fl |= 8;
5180  }
5181  }
5182  if (vec[2] < -vec[3]) {
5183  fl |= 16;
5184  }
5185  if (vec[2] > vec[3]) {
5186  fl |= 32;
5187  }
5188 
5189  flag &= fl;
5190  if (flag == 0) {
5191  return 0;
5192  }
5193  }
5194 
5195  return flag;
5196 }
5197 
5198 void box_minmax_bounds_m4(float min[3], float max[3], float boundbox[2][3], float mat[4][4])
5199 {
5200  float mn[3], mx[3], vec[3];
5201  int a;
5202 
5203  copy_v3_v3(mn, min);
5204  copy_v3_v3(mx, max);
5205 
5206  for (a = 0; a < 8; a++) {
5207  vec[0] = (a & 1) ? boundbox[0][0] : boundbox[1][0];
5208  vec[1] = (a & 2) ? boundbox[0][1] : boundbox[1][1];
5209  vec[2] = (a & 4) ? boundbox[0][2] : boundbox[1][2];
5210 
5211  mul_m4_v3(mat, vec);
5212  minmax_v3v3_v3(mn, mx, vec);
5213  }
5214 
5215  copy_v3_v3(min, mn);
5216  copy_v3_v3(max, mx);
5217 }
5218 
5219 /********************************** Mapping **********************************/
5220 
5221 void map_to_tube(float *r_u, float *r_v, const float x, const float y, const float z)
5222 {
5223  float len;
5224 
5225  *r_v = (z + 1.0f) / 2.0f;
5226 
5227  len = sqrtf(x * x + y * y);
5228  if (len > 0.0f) {
5229  *r_u = (1.0f - (atan2f(x / len, y / len) / (float)M_PI)) / 2.0f;
5230  }
5231  else {
5232  *r_v = *r_u = 0.0f; /* to avoid un-initialized variables */
5233  }
5234 }
5235 
5236 void map_to_sphere(float *r_u, float *r_v, const float x, const float y, const float z)
5237 {
5238  float len;
5239 
5240  len = sqrtf(x * x + y * y + z * z);
5241  if (len > 0.0f) {
5242  if (UNLIKELY(x == 0.0f && y == 0.0f)) {
5243  *r_u = 0.0f; /* Otherwise domain error. */
5244  }
5245  else {
5246  *r_u = (1.0f - atan2f(x, y) / (float)M_PI) / 2.0f;
5247  }
5248 
5249  *r_v = 1.0f - saacos(z / len) / (float)M_PI;
5250  }
5251  else {
5252  *r_v = *r_u = 0.0f; /* to avoid un-initialized variables */
5253  }
5254 }
5255 
5256 void map_to_plane_v2_v3v3(float r_co[2], const float co[3], const float no[3])
5257 {
5258  const float target[3] = {0.0f, 0.0f, 1.0f};
5259  float axis[3];
5260 
5261  cross_v3_v3v3(axis, no, target);
5262  normalize_v3(axis);
5263 
5264  map_to_plane_axis_angle_v2_v3v3fl(r_co, co, axis, angle_normalized_v3v3(no, target));
5265 }
5266 
5268  const float co[3],
5269  const float axis[3],
5270  const float angle)
5271 {
5272  float tmp[3];
5273 
5274  rotate_normalized_v3_v3v3fl(tmp, co, axis, angle);
5275 
5276  copy_v2_v2(r_co, tmp);
5277 }
5278 
5279 /********************************* Normals **********************************/
5280 
5282  float n2[3],
5283  float n3[3],
5284  const float f_no[3],
5285  const float co1[3],
5286  const float co2[3],
5287  const float co3[3])
5288 {
5289  float vdiffs[3][3];
5290  const int nverts = 3;
5291 
5292  /* compute normalized edge vectors */
5293  sub_v3_v3v3(vdiffs[0], co2, co1);
5294  sub_v3_v3v3(vdiffs[1], co3, co2);
5295  sub_v3_v3v3(vdiffs[2], co1, co3);
5296 
5297  normalize_v3(vdiffs[0]);
5298  normalize_v3(vdiffs[1]);
5299  normalize_v3(vdiffs[2]);
5300 
5301  /* accumulate angle weighted face normal */
5302  {
5303  float *vn[] = {n1, n2, n3};
5304  const float *prev_edge = vdiffs[nverts - 1];
5305  int i;
5306 
5307  for (i = 0; i < nverts; i++) {
5308  const float *cur_edge = vdiffs[i];
5309  const float fac = saacos(-dot_v3v3(cur_edge, prev_edge));
5310 
5311  /* accumulate */
5312  madd_v3_v3fl(vn[i], f_no, fac);
5313  prev_edge = cur_edge;
5314  }
5315  }
5316 }
5317 
5319  float n2[3],
5320  float n3[3],
5321  float n4[3],
5322  const float f_no[3],
5323  const float co1[3],
5324  const float co2[3],
5325  const float co3[3],
5326  const float co4[3])
5327 {
5328  float vdiffs[4][3];
5329  const int nverts = (n4 != NULL && co4 != NULL) ? 4 : 3;
5330 
5331  /* compute normalized edge vectors */
5332  sub_v3_v3v3(vdiffs[0], co2, co1);
5333  sub_v3_v3v3(vdiffs[1], co3, co2);
5334 
5335  if (nverts == 3) {
5336  sub_v3_v3v3(vdiffs[2], co1, co3);
5337  }
5338  else {
5339  sub_v3_v3v3(vdiffs[2], co4, co3);
5340  sub_v3_v3v3(vdiffs[3], co1, co4);
5341  normalize_v3(vdiffs[3]);
5342  }
5343 
5344  normalize_v3(vdiffs[0]);
5345  normalize_v3(vdiffs[1]);
5346  normalize_v3(vdiffs[2]);
5347 
5348  /* accumulate angle weighted face normal */
5349  {
5350  float *vn[] = {n1, n2, n3, n4};
5351  const float *prev_edge = vdiffs[nverts - 1];
5352  int i;
5353 
5354  for (i = 0; i < nverts; i++) {
5355  const float *cur_edge = vdiffs[i];
5356  const float fac = saacos(-dot_v3v3(cur_edge, prev_edge));
5357 
5358  /* accumulate */
5359  madd_v3_v3fl(vn[i], f_no, fac);
5360  prev_edge = cur_edge;
5361  }
5362  }
5363 }
5364 
5365 /* Add weighted face normal component into normals of the face vertices.
5366  * Caller must pass pre-allocated vdiffs of nverts length. */
5368  const float polyno[3],
5369  const float **vertcos,
5370  float vdiffs[][3],
5371  const int nverts)
5372 {
5373  int i;
5374 
5375  /* calculate normalized edge directions for each edge in the poly */
5376  for (i = 0; i < nverts; i++) {
5377  sub_v3_v3v3(vdiffs[i], vertcos[(i + 1) % nverts], vertcos[i]);
5378  normalize_v3(vdiffs[i]);
5379  }
5380 
5381  /* accumulate angle weighted face normal */
5382  {
5383  const float *prev_edge = vdiffs[nverts - 1];
5384 
5385  for (i = 0; i < nverts; i++) {
5386  const float *cur_edge = vdiffs[i];
5387 
5388  /* calculate angle between the two poly edges incident on
5389  * this vertex */
5390  const float fac = saacos(-dot_v3v3(cur_edge, prev_edge));
5391 
5392  /* accumulate */
5393  madd_v3_v3fl(vertnos[i], polyno, fac);
5394  prev_edge = cur_edge;
5395  }
5396  }
5397 }
5398 
5399 /********************************* Tangents **********************************/
5400 
5401 void tangent_from_uv_v3(const float uv1[2],
5402  const float uv2[2],
5403  const float uv3[3],
5404  const float co1[3],
5405  const float co2[3],
5406  const float co3[3],
5407  const float n[3],
5408  float r_tang[3])
5409 {
5410  const float s1 = uv2[0] - uv1[0];
5411  const float s2 = uv3[0] - uv1[0];
5412  const float t1 = uv2[1] - uv1[1];
5413  const float t2 = uv3[1] - uv1[1];
5414  float det = (s1 * t2 - s2 * t1);
5415 
5416  /* otherwise 'r_tang' becomes nan */
5417  if (det != 0.0f) {
5418  float tangv[3], ct[3], e1[3], e2[3];
5419 
5420  det = 1.0f / det;
5421 
5422  /* normals in render are inversed... */
5423  sub_v3_v3v3(e1, co1, co2);
5424  sub_v3_v3v3(e2, co1, co3);
5425  r_tang[0] = (t2 * e1[0] - t1 * e2[0]) * det;
5426  r_tang[1] = (t2 * e1[1] - t1 * e2[1]) * det;
5427  r_tang[2] = (t2 * e1[2] - t1 * e2[2]) * det;
5428  tangv[0] = (s1 * e2[0] - s2 * e1[0]) * det;
5429  tangv[1] = (s1 * e2[1] - s2 * e1[1]) * det;
5430  tangv[2] = (s1 * e2[2] - s2 * e1[2]) * det;
5431  cross_v3_v3v3(ct, r_tang, tangv);
5432 
5433  /* check flip */
5434  if (dot_v3v3(ct, n) < 0.0f) {
5435  negate_v3(r_tang);
5436  }
5437  }
5438  else {
5439  zero_v3(r_tang);
5440  }
5441 }
5442 
5443 /****************************** Vector Clouds ********************************/
5444 
5445 /* vector clouds */
5466 void vcloud_estimate_transform_v3(const int list_size,
5467  const float (*pos)[3],
5468  const float *weight,
5469  const float (*rpos)[3],
5470  const float *rweight,
5471  float lloc[3],
5472  float rloc[3],
5473  float lrot[3][3],
5474  float lscale[3][3])
5475 {
5476  float accu_com[3] = {0.0f, 0.0f, 0.0f}, accu_rcom[3] = {0.0f, 0.0f, 0.0f};
5477  float accu_weight = 0.0f, accu_rweight = 0.0f;
5478  const float eps = 1e-6f;
5479 
5480  int a;
5481  /* first set up a nice default response */
5482  if (lloc) {
5483  zero_v3(lloc);
5484  }
5485  if (rloc) {
5486  zero_v3(rloc);
5487  }
5488  if (lrot) {
5489  unit_m3(lrot);
5490  }
5491  if (lscale) {
5492  unit_m3(lscale);
5493  }
5494  /* do com for both clouds */
5495  if (pos && rpos && (list_size > 0)) { /* paranoia check */
5496  /* do com for both clouds */
5497  for (a = 0; a < list_size; a++) {
5498  if (weight) {
5499  float v[3];
5500  copy_v3_v3(v, pos[a]);
5501  mul_v3_fl(v, weight[a]);
5502  add_v3_v3(accu_com, v);
5503  accu_weight += weight[a];
5504  }
5505  else {
5506  add_v3_v3(accu_com, pos[a]);
5507  }
5508 
5509  if (rweight) {
5510  float v[3];
5511  copy_v3_v3(v, rpos[a]);
5512  mul_v3_fl(v, rweight[a]);
5513  add_v3_v3(accu_rcom, v);
5514  accu_rweight += rweight[a];
5515  }
5516  else {
5517  add_v3_v3(accu_rcom, rpos[a]);
5518  }
5519  }
5520  if (!weight || !rweight) {
5521  accu_weight = accu_rweight = (float)list_size;
5522  }
5523 
5524  mul_v3_fl(accu_com, 1.0f / accu_weight);
5525  mul_v3_fl(accu_rcom, 1.0f / accu_rweight);
5526  if (lloc) {
5527  copy_v3_v3(lloc, accu_com);
5528  }
5529  if (rloc) {
5530  copy_v3_v3(rloc, accu_rcom);
5531  }
5532  if (lrot || lscale) { /* caller does not want rot nor scale, strange but legal */
5533  /* so now do some reverse engineering and see if we can
5534  * split rotation from scale -> Polar-decompose. */
5535  /* build 'projection' matrix */
5536  float m[3][3], mr[3][3], q[3][3], qi[3][3];
5537  float va[3], vb[3], stunt[3];
5538  float odet, ndet;
5539  int i = 0, imax = 15;
5540  zero_m3(m);
5541  zero_m3(mr);
5542 
5543  /* build 'projection' matrix */
5544  for (a = 0; a < list_size; a++) {
5545  sub_v3_v3v3(va, rpos[a], accu_rcom);
5546  /* mul_v3_fl(va, bp->mass); mass needs re-normalization here ?? */
5547  sub_v3_v3v3(vb, pos[a], accu_com);
5548  /* mul_v3_fl(va, rp->mass); */
5549  m[0][0] += va[0] * vb[0];
5550  m[0][1] += va[0] * vb[1];
5551  m[0][2] += va[0] * vb[2];
5552 
5553  m[1][0] += va[1] * vb[0];
5554  m[1][1] += va[1] * vb[1];
5555  m[1][2] += va[1] * vb[2];
5556 
5557  m[2][0] += va[2] * vb[0];
5558  m[2][1] += va[2] * vb[1];
5559  m[2][2] += va[2] * vb[2];
5560 
5561  /* building the reference matrix on the fly
5562  * needed to scale properly later */
5563 
5564  mr[0][0] += va[0] * va[0];
5565  mr[0][1] += va[0] * va[1];
5566  mr[0][2] += va[0] * va[2];
5567 
5568  mr[1][0] += va[1] * va[0];
5569  mr[1][1] += va[1] * va[1];
5570  mr[1][2] += va[1] * va[2];
5571 
5572  mr[2][0] += va[2] * va[0];
5573  mr[2][1] += va[2] * va[1];
5574  mr[2][2] += va[2] * va[2];
5575  }
5576  copy_m3_m3(q, m);
5577  stunt[0] = q[0][0];
5578  stunt[1] = q[1][1];
5579  stunt[2] = q[2][2];
5580  /* Re-normalizing for numeric stability. */
5581  mul_m3_fl(q, 1.0f / len_v3(stunt));
5582 
5583  /* This is pretty much Polar-decompose 'inline' the algorithm based on Higham's thesis
5584  * without the far case ... but seems to work here pretty neat. */
5585  odet = 0.0f;
5586  ndet = determinant_m3_array(q);
5587  while ((odet - ndet) * (odet - ndet) > eps && i < imax) {
5588  invert_m3_m3(qi, q);
5589  transpose_m3(qi);
5590  add_m3_m3m3(q, q, qi);
5591  mul_m3_fl(q, 0.5f);
5592  odet = ndet;
5593  ndet = determinant_m3_array(q);
5594  i++;
5595  }
5596 
5597  if (i) {
5598  float scale[3][3];
5599  float irot[3][3];
5600  if (lrot) {
5601  copy_m3_m3(lrot, q);
5602  }
5603  invert_m3_m3(irot, q);
5604  invert_m3_m3(qi, mr);
5605  mul_m3_m3m3(q, m, qi);
5606  mul_m3_m3m3(scale, irot, q);
5607  if (lscale) {
5608  copy_m3_m3(lscale, scale);
5609  }
5610  }
5611  }
5612  }
5613 }
5614 
5615 /******************************* Form Factor *********************************/
5616 
5617 static void vec_add_dir(float r[3], const float v1[3], const float v2[3], const float fac)
5618 {
5619  r[0] = v1[0] + fac * (v2[0] - v1[0]);
5620  r[1] = v1[1] + fac * (v2[1] - v1[1]);
5621  r[2] = v1[2] + fac * (v2[2] - v1[2]);
5622 }
5623 
5624 bool form_factor_visible_quad(const float p[3],
5625  const float n[3],
5626  const float v0[3],
5627  const float v1[3],
5628  const float v2[3],
5629  float q0[3],
5630  float q1[3],
5631  float q2[3],
5632  float q3[3])
5633 {
5634  static const float epsilon = 1e-6f;
5635  float sd[3];
5636  const float c = dot_v3v3(n, p);
5637 
5638  /* signed distances from the vertices to the plane. */
5639  sd[0] = dot_v3v3(n, v0) - c;
5640  sd[1] = dot_v3v3(n, v1) - c;
5641  sd[2] = dot_v3v3(n, v2) - c;
5642 
5643  if (fabsf(sd[0]) < epsilon) {
5644  sd[0] = 0.0f;
5645  }
5646  if (fabsf(sd[1]) < epsilon) {
5647  sd[1] = 0.0f;
5648  }
5649  if (fabsf(sd[2]) < epsilon) {
5650  sd[2] = 0.0f;
5651  }
5652 
5653  if (sd[0] > 0.0f) {
5654  if (sd[1] > 0.0f) {
5655  if (sd[2] > 0.0f) {
5656  /* +++ */
5657  copy_v3_v3(q0, v0);
5658  copy_v3_v3(q1, v1);
5659  copy_v3_v3(q2, v2);
5660  copy_v3_v3(q3, q2);
5661  }
5662  else if (sd[2] < 0.0f) {
5663  /* ++- */
5664  copy_v3_v3(q0, v0);
5665  copy_v3_v3(q1, v1);
5666  vec_add_dir(q2, v1, v2, (sd[1] / (sd[1] - sd[2])));
5667  vec_add_dir(q3, v0, v2, (sd[0] / (sd[0] - sd[2])));
5668  }
5669  else {
5670  /* ++0 */
5671  copy_v3_v3(q0, v0);
5672  copy_v3_v3(q1, v1);
5673  copy_v3_v3(q2, v2);
5674  copy_v3_v3(q3, q2);
5675  }
5676  }
5677  else if (sd[1] < 0.0f) {
5678  if (sd[2] > 0.0f) {
5679  /* +-+ */
5680  copy_v3_v3(q0, v0);
5681  vec_add_dir(q1, v0, v1, (sd[0] / (sd[0] - sd[1])));
5682  vec_add_dir(q2, v1, v2, (sd[1] / (sd[1] - sd[2])));
5683  copy_v3_v3(q3, v2);
5684  }
5685  else if (sd[2] < 0.0f) {
5686  /* +-- */
5687  copy_v3_v3(q0, v0);
5688  vec_add_dir(q1, v0, v1, (sd[0] / (sd[0] - sd[1])));
5689  vec_add_dir(q2, v0, v2, (sd[0] / (sd[0] - sd[2])));
5690  copy_v3_v3(q3, q2);
5691  }
5692  else {
5693  /* +-0 */
5694  copy_v3_v3(q0, v0);
5695  vec_add_dir(q1, v0, v1, (sd[0] / (sd[0] - sd[1])));
5696  copy_v3_v3(q2, v2);
5697  copy_v3_v3(q3, q2);
5698  }
5699  }
5700  else {
5701  if (sd[2] > 0.0f) {
5702  /* +0+ */
5703  copy_v3_v3(q0, v0);
5704  copy_v3_v3(q1, v1);
5705  copy_v3_v3(q2, v2);
5706  copy_v3_v3(q3, q2);
5707  }
5708  else if (sd[2] < 0.0f) {
5709  /* +0- */
5710  copy_v3_v3(q0, v0);
5711  copy_v3_v3(q1, v1);
5712  vec_add_dir(q2, v0, v2, (sd[0] / (sd[0] - sd[2])));
5713  copy_v3_v3(q3, q2);
5714  }
5715  else {
5716  /* +00 */
5717  copy_v3_v3(q0, v0);
5718  copy_v3_v3(q1, v1);
5719  copy_v3_v3(q2, v2);
5720  copy_v3_v3(q3, q2);
5721  }
5722  }
5723  }
5724  else if (sd[0] < 0.0f) {
5725  if (sd[1] > 0.0f) {
5726  if (sd[2] > 0.0f) {
5727  /* -++ */
5728  vec_add_dir(q0, v0, v1, (sd[0] / (sd[0] - sd[1])));
5729  copy_v3_v3(q1, v1);
5730  copy_v3_v3(q2, v2);
5731  vec_add_dir(q3, v0, v2, (sd[0] / (sd[0] - sd[2])));
5732  }
5733  else if (sd[2] < 0.0f) {
5734  /* -+- */
5735  vec_add_dir(q0, v0, v1, (sd[0] / (sd[0] - sd[1])));
5736  copy_v3_v3(q1, v1);
5737  vec_add_dir(q2, v1, v2, (sd[1] / (sd[1] - sd[2])));
5738  copy_v3_v3(q3, q2);
5739  }
5740  else {
5741  /* -+0 */
5742  vec_add_dir(q0, v0, v1, (sd[0] / (sd[0] - sd[1])));
5743  copy_v3_v3(q1, v1);
5744  copy_v3_v3(q2, v2);
5745  copy_v3_v3(q3, q2);
5746  }
5747  }
5748  else if (sd[1] < 0.0f) {
5749  if (sd[2] > 0.0f) {
5750  /* --+ */
5751  vec_add_dir(q0, v0, v2, (sd[0] / (sd[0] - sd[2])));
5752  vec_add_dir(q1, v1, v2, (sd[1] / (sd[1] - sd[2])));
5753  copy_v3_v3(q2, v2);
5754  copy_v3_v3(q3, q2);
5755  }
5756  else if (sd[2] < 0.0f) {
5757  /* --- */
5758  return false;
5759  }
5760  else {
5761  /* --0 */
5762  return false;
5763  }
5764  }
5765  else {
5766  if (sd[2] > 0.0f) {
5767  /* -0+ */
5768  vec_add_dir(q0, v0, v2, (sd[0] / (sd[0] - sd[2])));
5769  copy_v3_v3(q1, v1);
5770  copy_v3_v3(q2, v2);
5771  copy_v3_v3(q3, q2);
5772  }
5773  else if (sd[2] < 0.0f) {
5774  /* -0- */
5775  return false;
5776  }
5777  else {
5778  /* -00 */
5779  return false;
5780  }
5781  }
5782  }
5783  else {
5784  if (sd[1] > 0.0f) {
5785  if (sd[2] > 0.0f) {
5786  /* 0++ */
5787  copy_v3_v3(q0, v0);
5788  copy_v3_v3(q1, v1);
5789  copy_v3_v3(q2, v2);
5790  copy_v3_v3(q3, q2);
5791  }
5792  else if (sd[2] < 0.0f) {
5793  /* 0+- */
5794  copy_v3_v3(q0, v0);
5795  copy_v3_v3(q1, v1);
5796  vec_add_dir(q2, v1, v2, (sd[1] / (sd[1] - sd[2])));
5797  copy_v3_v3(q3, q2);
5798  }
5799  else {
5800  /* 0+0 */
5801  copy_v3_v3(q0, v0);
5802  copy_v3_v3(q1, v1);
5803  copy_v3_v3(q2, v2);
5804  copy_v3_v3(q3, q2);
5805  }
5806  }
5807  else if (sd[1] < 0.0f) {
5808  if (sd[2] > 0.0f) {
5809  /* 0-+ */
5810  copy_v3_v3(q0, v0);
5811  vec_add_dir(q1, v1, v2, (sd[1] / (sd[1] - sd[2])));
5812  copy_v3_v3(q2, v2);
5813  copy_v3_v3(q3, q2);
5814  }
5815  else if (sd[2] < 0.0f) {
5816  /* 0-- */
5817  return false;
5818  }
5819  else {
5820  /* 0-0 */
5821  return false;
5822  }
5823  }
5824  else {
5825  if (sd[2] > 0.0f) {
5826  /* 00+ */
5827  copy_v3_v3(q0, v0);
5828  copy_v3_v3(q1, v1);
5829  copy_v3_v3(q2, v2);
5830  copy_v3_v3(q3, q2);
5831  }
5832  else if (sd[2] < 0.0f) {
5833  /* 00- */
5834  return false;
5835  }
5836  else {
5837  /* 000 */
5838  return false;
5839  }
5840  }
5841  }
5842 
5843  return true;
5844 }
5845 
5846 /* `AltiVec` optimization, this works, but is unused. */
5847 
5848 #if 0
5849 # include <Accelerate/Accelerate.h>
5850 
5851 typedef union {
5852  vFloat v;
5853  float f[4];
5854 } vFloatResult;
5855 
5856 static vFloat vec_splat_float(float val)
5857 {
5858  return (vFloat){val, val, val, val};
5859 }
5860 
5861 static float ff_quad_form_factor(float *p, float *n, float *q0, float *q1, float *q2, float *q3)
5862 {
5863  vFloat vcos, rlen, vrx, vry, vrz, vsrx, vsry, vsrz, gx, gy, gz, vangle;
5864  vUInt8 rotate = (vUInt8){4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3};
5865  vFloatResult vresult;
5866  float result;
5867 
5868  /* compute r* */
5869  vrx = (vFloat){q0[0], q1[0], q2[0], q3[0]} - vec_splat_float(p[0]);
5870  vry = (vFloat){q0[1], q1[1], q2[1], q3[1]} - vec_splat_float(p[1]);
5871  vrz = (vFloat){q0[2], q1[2], q2[2], q3[2]} - vec_splat_float(p[2]);
5872 
5873  /* normalize r* */
5874  rlen = vec_rsqrte(vrx * vrx + vry * vry + vrz * vrz + vec_splat_float(1e-16f));
5875  vrx = vrx * rlen;
5876  vry = vry * rlen;
5877  vrz = vrz * rlen;
5878 
5879  /* rotate r* for cross and dot */
5880  vsrx = vec_perm(vrx, vrx, rotate);
5881  vsry = vec_perm(vry, vry, rotate);
5882  vsrz = vec_perm(vrz, vrz, rotate);
5883 
5884  /* cross product */
5885  gx = vsry * vrz - vsrz * vry;
5886  gy = vsrz * vrx - vsrx * vrz;
5887  gz = vsrx * vry - vsry * vrx;
5888 
5889  /* normalize */
5890  rlen = vec_rsqrte(gx * gx + gy * gy + gz * gz + vec_splat_float(1e-16f));
5891  gx = gx * rlen;
5892  gy = gy * rlen;
5893  gz = gz * rlen;
5894 
5895  /* angle */
5896  vcos = vrx * vsrx + vry * vsry + vrz * vsrz;
5897  vcos = vec_max(vec_min(vcos, vec_splat_float(1.0f)), vec_splat_float(-1.0f));
5898  vangle = vacosf(vcos);
5899 
5900  /* dot */
5901  vresult.v = (vec_splat_float(n[0]) * gx + vec_splat_float(n[1]) * gy +
5902  vec_splat_float(n[2]) * gz) *
5903  vangle;
5904 
5905  result = (vresult.f[0] + vresult.f[1] + vresult.f[2] + vresult.f[3]) * (0.5f / (float)M_PI);
5906  result = MAX2(result, 0.0f);
5907 
5908  return result;
5909 }
5910 
5911 #endif
5912 
5913 /* SSE optimization, acos code doesn't work */
5914 
5915 #if 0
5916 
5917 # include "BLI_simd.h"
5918 
5919 static __m128 sse_approx_acos(__m128 x)
5920 {
5921  /* needs a better approximation than Taylor expansion of acos, since that
5922  * gives big errors for near 1.0 values, sqrt(2 * x) * acos(1 - x) should work
5923  * better, see http://www.tom.womack.net/projects/sse-fast-arctrig.html */
5924 
5925  return _mm_set_ps1(1.0f);
5926 }
5927 
5928 static float ff_quad_form_factor(float *p, float *n, float *q0, float *q1, float *q2, float *q3)
5929 {
5930  float r0[3], r1[3], r2[3], r3[3], g0[3], g1[3], g2[3], g3[3];
5931  float a1, a2, a3, a4, dot1, dot2, dot3, dot4, result;
5932  float fresult[4] __attribute__((aligned(16)));
5933  __m128 qx, qy, qz, rx, ry, rz, rlen, srx, sry, srz, gx, gy, gz, glen, rcos, angle, aresult;
5934 
5935  /* compute r */
5936  qx = _mm_set_ps(q3[0], q2[0], q1[0], q0[0]);
5937  qy = _mm_set_ps(q3[1], q2[1], q1[1], q0[1]);
5938  qz = _mm_set_ps(q3[2], q2[2], q1[2], q0[2]);
5939 
5940  rx = qx - _mm_set_ps1(p[0]);
5941  ry = qy - _mm_set_ps1(p[1]);
5942  rz = qz - _mm_set_ps1(p[2]);
5943 
5944  /* normalize r */
5945  rlen = _mm_rsqrt_ps(rx * rx + ry * ry + rz * rz + _mm_set_ps1(1e-16f));
5946  rx = rx * rlen;
5947  ry = ry * rlen;
5948  rz = rz * rlen;
5949 
5950  /* cross product */
5951  srx = _mm_shuffle_ps(rx, rx, _MM_SHUFFLE(0, 3, 2, 1));
5952  sry = _mm_shuffle_ps(ry, ry, _MM_SHUFFLE(0, 3, 2, 1));
5953  srz = _mm_shuffle_ps(rz, rz, _MM_SHUFFLE(0, 3, 2, 1));
5954 
5955  gx = sry * rz - srz * ry;
5956  gy = srz * rx - srx * rz;
5957  gz = srx * ry - sry * rx;
5958 
5959  /* normalize g */
5960  glen = _mm_rsqrt_ps(gx * gx + gy * gy + gz * gz + _mm_set_ps1(1e-16f));
5961  gx = gx * glen;
5962  gy = gy * glen;
5963  gz = gz * glen;
5964 
5965  /* compute angle */
5966  rcos = rx * srx + ry * sry + rz * srz;
5967  rcos = _mm_max_ps(_mm_min_ps(rcos, _mm_set_ps1(1.0f)), _mm_set_ps1(-1.0f));
5968 
5969  angle = sse_approx_cos(rcos);
5970  aresult = (_mm_set_ps1(n[0]) * gx + _mm_set_ps1(n[1]) * gy + _mm_set_ps1(n[2]) * gz) * angle;
5971 
5972  /* sum together */
5973  result = (fresult[0] + fresult[1] + fresult[2] + fresult[3]) * (0.5f / (float)M_PI);
5974  result = MAX2(result, 0.0f);
5975 
5976  return result;
5977 }
5978 
5979 #endif
5980 
5981 static void ff_normalize(float n[3])
5982 {
5983  float d;
5984 
5985  d = dot_v3v3(n, n);
5986 
5987  if (d > 1.0e-35f) {
5988  d = 1.0f / sqrtf(d);
5989 
5990  n[0] *= d;
5991  n[1] *= d;
5992  n[2] *= d;
5993  }
5994 }
5995 
5996 float form_factor_quad(const float p[3],
5997  const float n[3],
5998  const float q0[3],
5999  const float q1[3],
6000  const float q2[3],
6001  const float q3[3])
6002 {
6003  float r0[3], r1[3], r2[3], r3[3], g0[3], g1[3], g2[3], g3[3];
6004  float a1, a2, a3, a4, dot1, dot2, dot3, dot4, result;
6005 
6006  sub_v3_v3v3(r0, q0, p);
6007  sub_v3_v3v3(r1, q1, p);
6008  sub_v3_v3v3(r2, q2, p);
6009  sub_v3_v3v3(r3, q3, p);
6010 
6011  ff_normalize(r0);
6012  ff_normalize(r1);
6013  ff_normalize(r2);
6014  ff_normalize(r3);
6015 
6016  cross_v3_v3v3(g0, r1, r0);
6017  ff_normalize(g0);
6018  cross_v3_v3v3(g1, r2, r1);
6019  ff_normalize(g1);
6020  cross_v3_v3v3(g2, r3, r2);
6021  ff_normalize(g2);
6022  cross_v3_v3v3(g3, r0, r3);
6023  ff_normalize(g3);
6024 
6025  a1 = saacosf(dot_v3v3(r0, r1));
6026  a2 = saacosf(dot_v3v3(r1, r2));
6027  a3 = saacosf(dot_v3v3(r2, r3));
6028  a4 = saacosf(dot_v3v3(r3, r0));
6029 
6030  dot1 = dot_v3v3(n, g0);
6031  dot2 = dot_v3v3(n, g1);
6032  dot3 = dot_v3v3(n, g2);
6033  dot4 = dot_v3v3(n, g3);
6034 
6035  result = (a1 * dot1 + a2 * dot2 + a3 * dot3 + a4 * dot4) * 0.5f / (float)M_PI;
6036  result = MAX2(result, 0.0f);
6037 
6038  return result;
6039 }
6040 
6042  float p[3], float n[3], float v1[3], float v2[3], float v3[3], float v4[3])
6043 {
6044  /* computes how much hemisphere defined by point and normal is
6045  * covered by a quad or triangle, cosine weighted */
6046  float q0[3], q1[3], q2[3], q3[3], contrib = 0.0f;
6047 
6048  if (form_factor_visible_quad(p, n, v1, v2, v3, q0, q1, q2, q3)) {
6049  contrib += form_factor_quad(p, n, q0, q1, q2, q3);
6050  }
6051 
6052  if (v4 && form_factor_visible_quad(p, n, v1, v3, v4, q0, q1, q2, q3)) {
6053  contrib += form_factor_quad(p, n, q0, q1, q2, q3);
6054  }
6055 
6056  return contrib;
6057 }
6058 
6064 bool is_edge_convex_v3(const float v1[3],
6065  const float v2[3],
6066  const float f1_no[3],
6067  const float f2_no[3])
6068 {
6069  if (!equals_v3v3(f1_no, f2_no)) {
6070  float cross[3];
6071  float l_dir[3];
6072  cross_v3_v3v3(cross, f1_no, f2_no);
6073  /* we assume contiguous normals, otherwise the result isn't meaningful */
6074  sub_v3_v3v3(l_dir, v2, v1);
6075  return (dot_v3v3(l_dir, cross) > 0.0f);
6076  }
6077  return false;
6078 }
6079 
6083 bool is_quad_convex_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
6084 {
6094  /* non-unit length normal, used as a projection plane */
6095  float plane[3];
6096 
6097  {
6098  float v13[3], v24[3];
6099 
6100  sub_v3_v3v3(v13, v1, v3);
6101  sub_v3_v3v3(v24, v2, v4);
6102 
6103  cross_v3_v3v3(plane, v13, v24);
6104 
6105  if (len_squared_v3(plane) < FLT_EPSILON) {
6106  return false;
6107  }
6108  }
6109 
6110  const float *quad_coords[4] = {v1, v2, v3, v4};
6111  float quad_proj[4][3];
6112 
6113  for (int i = 0; i < 4; i++) {
6114  project_plane_v3_v3v3(quad_proj[i], quad_coords[i], plane);
6115  }
6116 
6117  float quad_dirs[4][3];
6118  for (int i = 0, j = 3; i < 4; j = i++) {
6119  sub_v3_v3v3(quad_dirs[i], quad_proj[i], quad_proj[j]);
6120  }
6121 
6122  float test_dir[3];
6123 
6124 #define CROSS_SIGN(dir_a, dir_b) \
6125  ((void)cross_v3_v3v3(test_dir, dir_a, dir_b), (dot_v3v3(plane, test_dir) > 0.0f))
6126 
6127  return (CROSS_SIGN(quad_dirs[0], quad_dirs[1]) && CROSS_SIGN(quad_dirs[1], quad_dirs[2]) &&
6128  CROSS_SIGN(quad_dirs[2], quad_dirs[3]) && CROSS_SIGN(quad_dirs[3], quad_dirs[0]));
6129 
6130 #undef CROSS_SIGN
6131 }
6132 
6133 bool is_quad_convex_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2])
6134 {
6135  /* Line-tests, the 2 diagonals have to intersect to be convex. */
6136  return (isect_seg_seg_v2(v1, v3, v2, v4) > 0);
6137 }
6138 
6139 bool is_poly_convex_v2(const float verts[][2], unsigned int nr)
6140 {
6141  unsigned int sign_flag = 0;
6142  unsigned int a;
6143  const float *co_curr, *co_prev;
6144  float dir_curr[2], dir_prev[2];
6145 
6146  co_prev = verts[nr - 1];
6147  co_curr = verts[0];
6148 
6149  sub_v2_v2v2(dir_prev, verts[nr - 2], co_prev);
6150 
6151  for (a = 0; a < nr; a++) {
6152  float cross;
6153 
6154  sub_v2_v2v2(dir_curr, co_prev, co_curr);
6155 
6156  cross = cross_v2v2(dir_prev, dir_curr);
6157 
6158  if (cross < 0.0f) {
6159  sign_flag |= 1;
6160  }
6161  else if (cross > 0.0f) {
6162  sign_flag |= 2;
6163  }
6164 
6165  if (sign_flag == (1 | 2)) {
6166  return false;
6167  }
6168 
6169  copy_v2_v2(dir_prev, dir_curr);
6170 
6171  co_prev = co_curr;
6172  co_curr += 2;
6173  }
6174 
6175  return true;
6176 }
6177 
6184 int is_quad_flip_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
6185 {
6186  float d_12[3], d_23[3], d_34[3], d_41[3];
6187  float cross_a[3], cross_b[3];
6188  int ret = 0;
6189 
6190  sub_v3_v3v3(d_12, v1, v2);
6191  sub_v3_v3v3(d_23, v2, v3);
6192  sub_v3_v3v3(d_34, v3, v4);
6193  sub_v3_v3v3(d_41, v4, v1);
6194 
6195  cross_v3_v3v3(cross_a, d_12, d_23);
6196  cross_v3_v3v3(cross_b, d_34, d_41);
6197  ret |= ((dot_v3v3(cross_a, cross_b) < 0.0f) << 0);
6198 
6199  cross_v3_v3v3(cross_a, d_23, d_34);
6200  cross_v3_v3v3(cross_b, d_41, d_12);
6201  ret |= ((dot_v3v3(cross_a, cross_b) < 0.0f) << 1);
6202 
6203  return ret;
6204 }
6205 
6207  const float v2[3],
6208  const float v3[3],
6209  const float v4[3])
6210 {
6211  float d_12[3], d_13[3], d_14[3];
6212  float cross_a[3], cross_b[3];
6213  sub_v3_v3v3(d_12, v2, v1);
6214  sub_v3_v3v3(d_13, v3, v1);
6215  sub_v3_v3v3(d_14, v4, v1);
6216  cross_v3_v3v3(cross_a, d_12, d_13);
6217  cross_v3_v3v3(cross_b, d_14, d_13);
6218  return dot_v3v3(cross_a, cross_b) > 0.0f;
6219 }
6220 
6229 float cubic_tangent_factor_circle_v3(const float tan_l[3], const float tan_r[3])
6230 {
6231  BLI_ASSERT_UNIT_V3(tan_l);
6232  BLI_ASSERT_UNIT_V3(tan_r);
6233 
6234  /* -7f causes instability/glitches with Bendy Bones + Custom Refs */
6235  const float eps = 1e-5f;
6236 
6237  const float tan_dot = dot_v3v3(tan_l, tan_r);
6238  if (tan_dot > 1.0f - eps) {
6239  /* no angle difference (use fallback, length wont make any difference) */
6240  return (1.0f / 3.0f) * 0.75f;
6241  }
6242  if (tan_dot < -1.0f + eps) {
6243  /* Parallel tangents (half-circle). */
6244  return (1.0f / 2.0f);
6245  }
6246 
6247  /* non-aligned tangents, calculate handle length */
6248  const float angle = acosf(tan_dot) / 2.0f;
6249 
6250  /* could also use 'angle_sin = len_vnvn(tan_l, tan_r, dims) / 2.0' */
6251  const float angle_sin = sinf(angle);
6252  const float angle_cos = cosf(angle);
6253  return ((1.0f - angle_cos) / (angle_sin * 2.0f)) / angle_sin;
6254 }
6255 
6265  const float v0[3], const float v1[3], const float v2[3], const float dist1, const float dist2)
6266 {
6267  /* Vectors along triangle edges. */
6268  float v10[3], v12[3];
6269  sub_v3_v3v3(v10, v0, v1);
6270  sub_v3_v3v3(v12, v2, v1);
6271 
6272  if (dist1 != 0.0f && dist2 != 0.0f) {
6273  /* Local coordinate system in the triangle plane. */
6274  float u[3], v[3], n[3];
6275  const float d12 = normalize_v3_v3(u, v12);
6276 
6277  if (d12 * d12 > 0.0f) {
6278  cross_v3_v3v3(n, v12, v10);
6279  normalize_v3(n);
6280  cross_v3_v3v3(v, n, u);
6281 
6282  /* v0 in local coordinates */
6283  const float v0_[2] = {dot_v3v3(v10, u), fabsf(dot_v3v3(v10, v))};
6284 
6285  /* Compute virtual source point in local coordinates, that we estimate the geodesic
6286  * distance is being computed from. See figure 9 in the paper for the derivation. */
6287  const float a = 0.5f * (1.0f + (dist1 * dist1 - dist2 * dist2) / (d12 * d12));
6288  const float hh = dist1 * dist1 - a * a * d12 * d12;
6289 
6290  if (hh > 0.0f) {
6291  const float h = sqrtf(hh);
6292  const float S_[2] = {a * d12, -h};
6293 
6294  /* Only valid if the line between the source point and v0 crosses
6295  * the edge between v1 and v2. */
6296  const float x_intercept = S_[0] + h * (v0_[0] - S_[0]) / (v0_[1] + h);
6297  if (x_intercept >= 0.0f && x_intercept <= d12) {
6298  return len_v2v2(S_, v0_);
6299  }
6300  }
6301  }
6302  }
6303 
6304  /* Fall back to Dijsktra approximation in trivial case, or if no valid source
6305  * point found that connects to v0 across the triangle. */
6306  return min_ff(dist1 + len_v3(v10), dist2 + len_v3v3(v0, v2));
6307 }
typedef float(TangentPoint)[2]
#define BLI_assert(a)
Definition: BLI_assert.h:58
sqrt(x)+1/max(0
MINLINE float saacos(float fac)
MINLINE float max_ff(float a, float b)
#define BLI_ASSERT_UNIT_EPSILON
MINLINE float min_ff(float a, float b)
MINLINE float saacosf(float f)
MINLINE float square_f(float a)
#define BLI_ASSERT_UNIT_V3(v)
#define M_PI
Definition: BLI_math_base.h:38
MINLINE int float_as_int(float f)
MINLINE float xor_fl(float x, int y)
MINLINE float area_tri_v2(const float v1[2], const float v2[2], const float v3[2])
#define ISECT_AABB_PLANE_IN_FRONT_ALL
MINLINE int axis_dominant_v3_single(const float vec[3])
MINLINE float cross_tri_v2(const float v1[2], const float v2[2], const float v3[2])
#define ISECT_LINE_LINE_NONE
MINLINE float plane_point_side_v3(const float plane[4], const float co[3])
#define ISECT_AABB_PLANE_CROSS_ANY
#define ISECT_AABB_PLANE_BEHIND_ANY
#define ISECT_LINE_LINE_COLINEAR
bool isect_ray_tri_threshold_v3(const float ray_origin[3], const float ray_direction[3], const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2], const float threshold)
#define ISECT_LINE_LINE_EXACT
MINLINE void axis_dominant_v3(int *r_axis_a, int *r_axis_b, const float axis[3])
#define ISECT_LINE_LINE_CROSS
bool is_negative_m3(const float mat[3][3])
Definition: math_matrix.c:2583
void mul_m4_v4(const float M[4][4], float r[4])
Definition: math_matrix.c:866
void copy_m3_m3(float m1[3][3], const float m2[3][3])
Definition: math_matrix.c:89
void unit_m3(float m[3][3])
Definition: math_matrix.c:58
void transpose_m4_m4(float R[4][4], const float M[4][4])
Definition: math_matrix.c:1384
void mul_m3_fl(float R[3][3], float f)
Definition: math_matrix.c:960
void unit_m4(float m[4][4])
Definition: rct.c:1140
void add_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
Definition: math_matrix.c:1036
void translate_m4(float mat[4][4], float tx, float ty, float tz)
Definition: math_matrix.c:2325
void zero_m3(float m[3][3])
Definition: math_matrix.c:41
void copy_m4d_m4(double m1[4][4], const float m2[4][4])
Definition: math_matrix.c:183
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:732
bool invert_m3_m3(float R[3][3], const float A[3][3])
Definition: math_matrix.c:1161
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:95
float determinant_m3_array(const float m[3][3])
Definition: math_matrix.c:1102
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
Definition: math_matrix.c:901
void transpose_m3(float R[3][3])
Definition: math_matrix.c:1312
float determinant_m3(float a1, float a2, float a3, float b1, float b2, float b3, float c1, float c2, float c3)
Definition: math_matrix.c:2059
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
Definition: math_matrix.c:391
void rotate_m4(float mat[4][4], const char axis, const float angle)
Definition: math_matrix.c:2352
void axis_angle_to_mat4_single(float R[4][4], const char axis, const float angle)
MINLINE void sub_v3db_v3fl_v3fl(double r[3], const float a[3], const float b[3])
MINLINE void mul_v4_fl(float r[4], float f)
void interp_v2_v2v2(float r[2], const float a[2], const float b[2], const float t)
Definition: math_vector.c:32
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], const float t)
Definition: math_vector.c:49
MINLINE float len_squared_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
Definition: math_vector.c:1020
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE float len_squared_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE double dot_v2v2_db(const double a[2], const double b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v2_v2fl(float r[2], const float a[2], float f)
MINLINE void madd_v2_v2v2fl(float r[2], const float a[2], const float b[2], float f)
MINLINE float normalize_v3(float r[3])
void interp_v3_v3v3v3(float p[3], const float v1[3], const float v2[3], const float v3[3], const float w[3])
Definition: math_vector.c:191
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE double dot_v3db_v3fl(const double a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_newell_cross_v3_v3v3(float n[3], const float v_prev[3], const float v_curr[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v2_v2(float r[2], const float a[2])
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])
void project_v3_v3v3_normalized(float out[3], const float p[3], const float v_proj[3])
Definition: math_vector.c:717
MINLINE bool is_zero_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
void project_v3_v3v3(float out[3], const float p[3], const float v_proj[3])
Definition: math_vector.c:674
void project_plane_v3_v3v3(float out[3], const float p[3], const float v_plane[3])
Definition: math_vector.c:740
bool is_finite_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:398
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE bool equals_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void negate_v3(float r[3])
MINLINE float dot_m3_v3_row_z(const float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float cross_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void zero_v4(float r[4])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE float line_point_side_v2(const float l1[2], const float l2[2], const float pt[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void zero_v2(float r[2])
bool is_finite_v4(const float a[4]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:403
MINLINE float mul_project_m4_v3_zfac(const float mat[4][4], const float co[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void cross_v3_v3v3_db(double r[3], const double a[3], const double b[3])
MINLINE float dot_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE bool equals_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void ortho_basis_v3v3_v3(float r_n1[3], float r_n2[3], const float n[3])
Definition: math_vector.c:845
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
MINLINE float len_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_v2(const float a[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void zero_v3(float r[3])
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void mul_v2_v2fl(float r[2], const float a[2], float f)
float angle_normalized_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:505
MINLINE float dot_m4_v3_row_x(const float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE void copy_v4_fl(float r[4], float f)
MINLINE float dot_m4_v3_row_y(const float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT
void rotate_normalized_v3_v3v3fl(float out[3], const float p[3], const float axis[3], const float angle)
Definition: math_vector.c:929
MINLINE double cross_v2v2_db(const double a[2], const double b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v2_v2v2_db(double r[2], const double a[2], const double b[2])
Strict compiler flags for areas of code we want to ensure don't do conversions without us knowing abo...
#define UNUSED_VARS(...)
#define SWAP(type, a, b)
#define IN_RANGE(a, b, c)
#define UNUSED(x)
#define UNPACK3(a)
#define MAX2(a, b)
#define UNLIKELY(x)
#define ELEM(...)
#define IN_RANGE_INCL(a, b, c)
#define LIKELY(x)
int rect_width(int rect[2][2])
Definition: Basic.c:58
int rect_height(int rect[2][2])
Definition: Basic.c:62
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 y1
_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 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 vn
_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 x2
_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 right
_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 top
_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 const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
_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 bottom
Read Guarded memory(de)allocation.
Group RGB to Bright Vector Camera CLAMP
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition: btDbvt.cpp:299
btScalar determinant() const
Return the determinant of the matrix.
Definition: btMatrix3x3.h:1022
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
SIMD_FORCE_INLINE btScalar length(const btQuaternion &q)
Return the length of a quaternion.
Definition: btQuaternion.h:895
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
SIMD_FORCE_INLINE btVector3 rotate(const btVector3 &wAxis, const btScalar angle) const
Return a rotated version of this vector.
bool closest(btVector3 &v)
void * user_data
static float verts[][3]
uint pos
uint nor
uint col
IconTextureDrawCall normal
#define sinf(x)
#define cosf(x)
#define tanf(x)
#define atan2f(x, y)
#define acosf(x)
#define copysignf(x, y)
#define fabsf(x)
#define sqrtf(x)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void map_to_sphere(float *r_u, float *r_v, const float x, const float y, const float z)
Definition: math_geom.c:5236
bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const unsigned int nr, const bool UNUSED(use_holes))
Definition: math_geom.c:1558
int isect_seg_seg_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2])
Definition: math_geom.c:1151
static void ff_normalize(float n[3])
Definition: math_geom.c:5981
float dist_signed_squared_to_plane3_v3(const float pt[3], const float plane[3])
Definition: math_geom.c:449
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
Definition: math_geom.c:243
bool isect_ray_ray_v3(const float ray_origin_a[3], const float ray_direction_a[3], const float ray_origin_b[3], const float ray_direction_b[3], float *r_lambda_a, float *r_lambda_b)
Definition: math_geom.c:3210
#define IS_ZERO(x)
Definition: math_geom.c:4552
float closest_to_ray_v3(float r_close[3], const float p[3], const float ray_orig[3], const float ray_dir[3])
Definition: math_geom.c:3341
void isect_ray_tri_watertight_v3_precalc(struct IsectRayPrecalc *isect_precalc, const float ray_direction[3])
Definition: math_geom.c:1879
void window_translate_m4(float winmat[4][4], float perspmat[4][4], const float x, const float y)
Definition: math_geom.c:4877
float dist_squared_to_line_v3(const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:507
float dist_squared_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:493
float area_squared_poly_v2(const float verts[][2], unsigned int nr)
Definition: math_geom.c:214
float dist_squared_to_projected_aabb(struct DistProjectedAABBPrecalc *data, const float bbmin[3], const float bbmax[3], bool r_axis_closest[3])
Definition: math_geom.c:875
float normal_quad_v3(float n[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition: math_geom.c:68
int isect_line_line_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3], float r_i1[3], float r_i2[3])
Definition: math_geom.c:3103
float line_point_factor_v2_ex(const float p[2], const float l1[2], const float l2[2], const float epsilon, const float fallback)
Definition: math_geom.c:3454
void orthographic_m4(float matrix[4][4], const float left, const float right, const float bottom, const float top, const float nearClip, const float farClip)
Definition: math_geom.c:4802
static bool getLowestRoot(const float a, const float b, const float c, const float maxR, float *root)
Definition: math_geom.c:2722
bool isect_ray_line_v3(const float ray_origin[3], const float ray_direction[3], const float v0[3], const float v1[3], float *r_lambda)
Definition: math_geom.c:2123
int barycentric_inside_triangle_v2(const float w[3])
Definition: math_geom.c:3897
int is_quad_flip_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition: math_geom.c:6184
static double mean_value_half_tan_v2_db(const struct Double2_Len *d_curr, const struct Double2_Len *d_next)
Definition: math_geom.c:4323
void transform_point_by_seg_v3(float p_dst[3], const float p_src[3], const float l_dst_p1[3], const float l_dst_p2[3], const float l_src_p1[3], const float l_src_p2[3])
Definition: math_geom.c:4169
bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const float radius, const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float ipoint[3])
Definition: math_geom.c:2788
bool isect_ray_tri_v3(const float ray_origin[3], const float ray_direction[3], const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2])
Definition: math_geom.c:1751
float area_poly_v3(const float verts[][3], unsigned int nr)
Definition: math_geom.c:149
void barycentric_weights_v2(const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3])
Definition: math_geom.c:3943
void accumulate_vertex_normals_tri_v3(float n1[3], float n2[3], float n3[3], const float f_no[3], const float co1[3], const float co2[3], const float co3[3])
Definition: math_geom.c:5281
float ray_point_factor_v3(const float p[3], const float ray_origin[3], const float ray_direction[3])
Definition: math_geom.c:3420
float dist_to_plane_v3(const float pt[3], const float plane[4])
Definition: math_geom.c:475
void barycentric_weights_v2_clamped(const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3])
Definition: math_geom.c:3971
#define IS_POINT_IX
Definition: math_geom.c:4269
void isect_seg_seg_v3(const float a0[3], const float a1[3], const float b0[3], const float b1[3], float r_a[3], float r_b[3])
Definition: math_geom.c:1174
float form_factor_quad(const float p[3], const float n[3], const float q0[3], const float q1[3], const float q2[3], const float q3[3])
Definition: math_geom.c:5996
double closest_to_line_v2_db(double r_close[2], const double p[2], const double l1[2], const double l2[2])
Definition: math_geom.c:3388
bool isect_line_segment_tri_epsilon_v3(const float p1[3], const float p2[3], const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2], const float epsilon)
Definition: math_geom.c:1696
void cross_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:36
bool point_in_slice_seg(float p[3], float l1[3], float l2[3])
Definition: math_geom.c:3580
bool isect_tri_tri_v2(const float t_a0[2], const float t_a1[2], const float t_a2[2], const float t_b0[2], const float t_b1[2], const float t_b2[2])
Definition: math_geom.c:2695
void transform_point_by_tri_v3(float pt_tar[3], float const pt_src[3], const float tri_tar_p1[3], const float tri_tar_p2[3], const float tri_tar_p3[3], const float tri_src_p1[3], const float tri_src_p2[3], const float tri_src_p3[3])
Definition: math_geom.c:4121
void projmat_dimensions_db(const float projmat_fl[4][4], double *r_left, double *r_right, double *r_bottom, double *r_top, double *r_near, double *r_far)
Definition: math_geom.c:4992
void polarview_m4(float mat[4][4], float dist, float azimuth, float incidence, float twist)
Definition: math_geom.c:5076
int isect_seg_seg_v2_lambda_mu_db(const double v1[2], const double v2[2], const double v3[2], const double v4[2], double *r_lambda, double *r_mu)
Definition: math_geom.c:1384
void interp_weights_quad_v3(float w[4], const float v1[3], const float v2[3], const float v3[3], const float v4[3], const float co[3])
Definition: math_geom.c:3840
float area_tri_signed_v3(const float v1[3], const float v2[3], const float v3[3], const float normal[3])
Definition: math_geom.c:131
float volume_tri_tetrahedron_signed_v3_6x(const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:307
void closest_to_plane3_normalized_v3(float r_close[3], const float plane[3], const float pt[3])
Definition: math_geom.c:426
bool isect_seg_seg_v2_simple(const float v1[2], const float v2[2], const float v3[2], const float v4[2])
Definition: math_geom.c:1360
float dist_to_plane3_v3(const float pt[3], const float plane[3])
Definition: math_geom.c:487
#define DIR_V3_SET(d_len, va, vb)
Definition: math_geom.c:4272
void closest_to_plane_normalized_v3(float r_close[3], const float plane[4], const float pt[3])
Definition: math_geom.c:412
int isect_point_tri_v2_int(const int x1, const int y1, const int x2, const int y2, const int a, const int b)
Definition: math_geom.c:3518
bool isect_point_tri_v3(const float p[3], const float v1[3], const float v2[3], const float v3[3], float r_isect_co[3])
Definition: math_geom.c:3612
void interp_weights_tri_v3(float w[3], const float v1[3], const float v2[3], const float v3[3], const float co[3])
Definition: math_geom.c:3831
void resolve_tri_uv_v2(float r_uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2])
Definition: math_geom.c:4561
float line_point_factor_v3_ex(const float p[3], const float l1[3], const float l2[3], const float epsilon, const float fallback)
Definition: math_geom.c:3434
float dist_signed_to_plane_v3(const float pt[3], const float plane[4])
Definition: math_geom.c:468
bool isect_ray_aabb_v3(const struct IsectRayAABB_Precalc *data, const float bb_min[3], const float bb_max[3], float *tmin_out)
Definition: math_geom.c:3251
bool isect_ray_aabb_v3_simple(const float orig[3], const float dir[3], const float bb_min[3], const float bb_max[3], float *tmin, float *tmax)
Definition: math_geom.c:3308
float dist_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:502
static float mean_value_half_tan_v3(const struct Float3_Len *d_curr, const struct Float3_Len *d_next)
Definition: math_geom.c:4296
bool isect_aabb_aabb_v3(const float min1[3], const float max1[3], const float min2[3], const float max2[3])
Definition: math_geom.c:3226
float area_squared_poly_v3(const float verts[][3], unsigned int nr)
Definition: math_geom.c:156
void vcloud_estimate_transform_v3(const int list_size, const float(*pos)[3], const float *weight, const float(*rpos)[3], const float *rweight, float lloc[3], float rloc[3], float lrot[3][3], float lscale[3][3])
Definition: math_geom.c:5466
static void i_multmatrix(const float icand[4][4], float mat[4][4])
Definition: math_geom.c:5062
void dist_squared_ray_to_aabb_v3_precalc(struct DistRayAABB_Precalc *neasrest_precalc, const float ray_origin[3], const float ray_direction[3])
Definition: math_geom.c:696
void projmat_from_subregion(const float projmat[4][4], const int win_size[2], const int x_min, const int x_max, const int y_min, const int y_max, float r_projmat[4][4])
Definition: math_geom.c:5031
bool isect_point_poly_v2(const float pt[2], const float verts[][2], const unsigned int nr, const bool UNUSED(use_holes))
Definition: math_geom.c:1541
float volume_tri_tetrahedron_signed_v3(const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:315
float dist_signed_to_plane3_v3(const float pt[3], const float plane[3])
Definition: math_geom.c:480
void cross_poly_v3(float n[3], const float verts[][3], unsigned int nr)
Definition: math_geom.c:190
#define CCW(A, B, C)
bool isect_line_plane_v3(float r_isect_co[3], const float l1[3], const float l2[3], const float plane_co[3], const float plane_no[3])
Definition: math_geom.c:2191
bool isect_ray_seg_v2(const float ray_origin[2], const float ray_direction[2], const float v0[2], const float v1[2], float *r_lambda, float *r_u)
Definition: math_geom.c:2077
void closest_to_line_segment_v2(float r_close[2], const float p[2], const float l1[2], const float l2[2])
Definition: math_geom.c:353
float dist_squared_to_projected_aabb_simple(const float projmat[4][4], const float winsize[2], const float mval[2], const float bbmin[3], const float bbmax[3])
Definition: math_geom.c:1005
void accumulate_vertex_normals_poly_v3(float **vertnos, const float polyno[3], const float **vertcos, float vdiffs[][3], const int nverts)
Definition: math_geom.c:5367
void tangent_from_uv_v3(const float uv1[2], const float uv2[2], const float uv3[3], const float co1[3], const float co2[3], const float co3[3], const float n[3], float r_tang[3])
Definition: math_geom.c:5401
int isect_point_quad_v2(const float pt[2], const float v1[2], const float v2[2], const float v3[2], const float v4[2])
Definition: math_geom.c:1616
float dist_squared_ray_to_aabb_v3_simple(const float ray_origin[3], const float ray_direction[3], const float bb_min[3], const float bb_max[3], float r_point[3], float *r_depth)
Definition: math_geom.c:802
static bool point_in_slice(const float p[3], const float v1[3], const float l1[3], const float l2[3])
Definition: math_geom.c:3538
bool is_quad_flip_v3_first_third_fast(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition: math_geom.c:6206
#define DIR_V2_SET(d_len, va, vb)
Definition: math_geom.c:4279
#define MEAN_VALUE_HALF_TAN_V2(_area, i1, i2)
float form_factor_hemi_poly(float p[3], float n[3], float v1[3], float v2[3], float v3[3], float v4[3])
Definition: math_geom.c:6041
bool clip_segment_v3_plane(const float p1[3], const float p2[3], const float plane[4], float r_p1[3], float r_p2[3])
Definition: math_geom.c:3632
void closest_to_plane3_v3(float r_close[3], const float plane[3], const float pt[3])
Definition: math_geom.c:419
bool isect_plane_plane_plane_v3(const float plane_a[4], const float plane_b[4], const float plane_c[4], float r_isect_co[3])
Definition: math_geom.c:2221
void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[2])
Definition: math_geom.c:4425
void resolve_quad_uv_v2(float r_uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2])
Definition: math_geom.c:4620
void projmat_dimensions(const float projmat[4][4], float *r_left, float *r_right, float *r_bottom, float *r_top, float *r_near, float *r_far)
Definition: math_geom.c:4964
float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2])
Definition: math_geom.c:3469
bool isect_ray_tri_watertight_v3_simple(const float ray_origin[3], const float ray_direction[3], const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2])
Definition: math_geom.c:1981
void closest_on_tri_to_point_v3(float r[3], const float p[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:1023
static void vec_add_dir(float r[3], const float v1[3], const float v2[3], const float fac)
Definition: math_geom.c:5617
void perspective_m4(float mat[4][4], const float left, const float right, const float bottom, const float top, const float nearClip, const float farClip)
Definition: math_geom.c:4830
static bool isect_tri_tri_v2_impl_vert(const float t_a0[2], const float t_a1[2], const float t_a2[2], const float t_b0[2], const float t_b1[2], const float t_b2[2])
Definition: math_geom.c:2550
void lookat_m4(float mat[4][4], float vx, float vy, float vz, float px, float py, float pz, float twist)
Definition: math_geom.c:5086
void axis_dominant_v3_to_m3_negate(float r_mat[3][3], const float normal[3])
Definition: math_geom.c:3772
static bool barycentric_weights(const float v1[3], const float v2[3], const float v3[3], const float co[3], const float n[3], float w[3])
Definition: math_geom.c:3799
void accumulate_vertex_normals_v3(float n1[3], float n2[3], float n3[3], float n4[3], const float f_no[3], const float co1[3], const float co2[3], const float co3[3], const float co4[3])
Definition: math_geom.c:5318
bool isect_tri_tri_v3(const float t_a0[3], const float t_a1[3], const float t_a2[3], const float t_b0[3], const float t_b1[3], const float t_b2[3], float r_i1[3], float r_i2[3])
Definition: math_geom.c:2521
float line_plane_factor_v3(const float plane_co[3], const float plane_no[3], const float l1[3], const float l2[3])
Definition: math_geom.c:3477
static int isect_tri_tri_impl_ccw_v2(const float t_a0[2], const float t_a1[2], const float t_a2[2], const float t_b0[2], const float t_b1[2], const float t_b2[2])
Definition: math_geom.c:2661
void dist_squared_to_projected_aabb_precalc(struct DistProjectedAABBPrecalc *precalc, const float projmat[4][4], const float winsize[2], const float mval[2])
Definition: math_geom.c:823
#define IS_SEGMENT_IX
Definition: math_geom.c:4270
void aabb_get_near_far_from_plane(const float plane_no[3], const float bbmin[3], const float bbmax[3], float bb_near[3], float bb_afar[3])
Definition: math_geom.c:660
float dist_squared_to_plane_v3(const float pt[3], const float plane[4])
Definition: math_geom.c:440
void resolve_tri_uv_v3(float r_uv[2], const float st[3], const float st0[3], const float st1[3], const float st2[3])
Definition: math_geom.c:4588
void isect_ray_aabb_v3_precalc(struct IsectRayAABB_Precalc *data, const float ray_origin[3], const float ray_direction[3])
Definition: math_geom.c:3235
bool isect_plane_plane_v3(const float plane_a[4], const float plane_b[4], float r_isect_co[3], float r_isect_no[3])
Definition: math_geom.c:2265
float area_tri_v3(const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:116
bool isect_point_tri_v2_cw(const float pt[2], const float v1[2], const float v2[2], const float v3[2])
Definition: math_geom.c:1579
float area_poly_signed_v2(const float verts[][2], unsigned int nr)
Definition: math_geom.c:209
bool isect_ray_tri_watertight_v3(const float ray_origin[3], const struct IsectRayPrecalc *isect_precalc, const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2])
Definition: math_geom.c:1906
int isect_line_sphere_v3(const float l1[3], const float l2[3], const float sp[3], const float r, float r_p1[3], float r_p2[3])
Definition: math_geom.c:1431
bool is_quad_convex_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition: math_geom.c:6083
bool is_edge_convex_v3(const float v1[3], const float v2[3], const float f1_no[3], const float f2_no[3])
Definition: math_geom.c:6064
float resolve_quad_u_v2(const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2])
Definition: math_geom.c:4722
float dist_signed_squared_to_plane_v3(const float pt[3], const float plane[4])
Definition: math_geom.c:433
void axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3])
Normal to x,y matrix.
Definition: math_geom.c:3752
void interp_barycentric_tri_v3(float data[3][3], float u, float v, float res[3])
Definition: math_geom.c:4783
float volume_tetrahedron_signed_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition: math_geom.c:289
void perspective_m4_fov(float mat[4][4], const float angle_left, const float angle_right, const float angle_up, const float angle_down, const float nearClip, const float farClip)
Definition: math_geom.c:4856
static bool point_in_slice_as(const float p[3], const float origin[3], const float normal[3])
Definition: math_geom.c:3569
bool isect_line_line_strict_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3], float vi[3], float *r_lambda)
Definition: math_geom.c:3118
void interp_cubic_v3(float x[3], float v[3], const float x1[3], const float v1[3], const float x2[3], const float v2[3], const float t)
Definition: math_geom.c:4519
static bool isect_tri_tri_v2_impl_edge(const float t_a0[2], const float t_a1[2], const float t_a2[2], const float t_b0[2], const float t_b1[2], const float t_b2[2])
Definition: math_geom.c:2613
float area_squared_tri_v3(const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:123
bool isect_tri_tri_v3_ex(const float tri_a[3][3], const float tri_b[3][3], float r_i1[3], float r_i2[3], int *r_tri_a_edge_isect_count)
Definition: math_geom.c:2384
float dist_squared_ray_to_seg_v3(const float ray_origin[3], const float ray_direction[3], const float v0[3], const float v1[3], float r_point[3], float *r_depth)
Definition: math_geom.c:622
float dist_squared_ray_to_aabb_v3(const struct DistRayAABB_Precalc *data, const float bb_min[3], const float bb_max[3], float r_point[3], float *r_depth)
Definition: math_geom.c:713
void barycentric_weights_v2_quad(const float v1[2], const float v2[2], const float v3[2], const float v4[2], const float co[2], float w[4])
Definition: math_geom.c:4026
int isect_line_sphere_v2(const float l1[2], const float l2[2], const float sp[2], const float r, float r_p1[2], float r_p2[2])
Definition: math_geom.c:1494
float geodesic_distance_propagate_across_triangle(const float v0[3], const float v1[3], const float v2[3], const float dist1, const float dist2)
Definition: math_geom.c:6264
int box_clip_bounds_m4(float boundbox[2][3], const float bounds[4], float winmat[4][4])
Definition: math_geom.c:5139
bool isect_planes_v3_fn(const float planes[][4], const int planes_len, const float eps_coplanar, const float eps_isect, void(*callback_fn)(const float co[3], int i, int j, int k, void *user_data), void *user_data)
Definition: math_geom.c:2312
float cubic_tangent_factor_circle_v3(const float tan_l[3], const float tan_r[3])
Definition: math_geom.c:6229
float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:3449
float dist_squared_to_ray_v3_normalized(const float ray_origin[3], const float ray_direction[3], const float co[3])
Definition: math_geom.c:600
float area_squared_quad_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition: math_geom.c:106
void limit_dist_v3(float v1[3], float v2[3], const float dist)
Definition: math_geom.c:3494
bool barycentric_coords_v2(const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3])
Definition: math_geom.c:3913
int isect_line_line_v2_point(const float v0[2], const float v1[2], const float v2[2], const float v3[2], float r_vi[2])
Definition: math_geom.c:1127
void closest_to_plane_v3(float r_close[3], const float plane[4], const float pt[3])
Definition: math_geom.c:405
void plane_to_point_vector_v3(const float plane[4], float r_plane_co[3], float r_plane_no[3])
Definition: math_geom.c:252
int isect_seg_seg_v2_point_ex(const float v0[2], const float v1[2], const float v2[2], const float v3[2], const float endpoint_bias, float r_vi[2])
Definition: math_geom.c:1252
float cross_poly_v2(const float verts[][2], unsigned int nr)
Definition: math_geom.c:171
float closest_to_line_v2(float r_close[2], const float p[2], const float l1[2], const float l2[2])
Definition: math_geom.c:3371
float dist_to_line_segment_v2(const float p[2], const float l1[2], const float l2[2])
Definition: math_geom.c:347
#define CROSS_SIGN(dir_a, dir_b)
void map_to_tube(float *r_u, float *r_v, const float x, const float y, const float z)
Definition: math_geom.c:5221
float closest_to_line_v3(float r_close[3], const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:3364
void map_to_plane_v2_v3v3(float r_co[2], const float co[3], const float no[3])
Definition: math_geom.c:5256
void planes_from_projmat(const float mat[4][4], float left[4], float right[4], float top[4], float bottom[4], float near[4], float far[4])
Definition: math_geom.c:4911
bool is_quad_convex_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2])
Definition: math_geom.c:6133
float cotangent_tri_weight_v3(const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:220
void resolve_quad_uv_v2_deriv(float r_uv[2], float r_deriv[2][2], const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2])
Definition: math_geom.c:4631
bool isect_ray_ray_epsilon_v3(const float ray_origin_a[3], const float ray_direction_a[3], const float ray_origin_b[3], const float ray_direction_b[3], const float epsilon, float *r_lambda_a, float *r_lambda_b)
Definition: math_geom.c:3174
void barycentric_weights_v2_persp(const float v1[4], const float v2[4], const float v3[4], const float co[2], float w[3])
Definition: math_geom.c:3998
void closest_to_line_segment_v3(float r_close[3], const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:375
float dist_to_line_v3(const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:515
float ray_point_factor_v3_ex(const float p[3], const float ray_origin[3], const float ray_direction[3], const float epsilon, const float fallback)
Definition: math_geom.c:3408
static float tri_signed_area(const float v1[3], const float v2[3], const float v3[3], const int i, const int j)
Definition: math_geom.c:3790
int interp_sparse_array(float *array, const int list_size, const float skipval)
Definition: math_geom.c:4182
bool isect_ray_tri_epsilon_v3(const float ray_origin[3], const float ray_direction[3], const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2], const float epsilon)
Definition: math_geom.c:1830
float dist_squared_to_line_v2(const float p[2], const float l1[2], const float l2[2])
Definition: math_geom.c:324
int isect_line_line_epsilon_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3], float r_i1[3], float r_i2[3], const float epsilon)
Definition: math_geom.c:3039
bool form_factor_visible_quad(const float p[3], const float n[3], const float v0[3], const float v1[3], const float v2[3], float q0[3], float q1[3], float q2[3], float q3[3])
Definition: math_geom.c:5624
int isect_seg_seg_v2_int(const int v1[2], const int v2[2], const int v3[2], const int v4[2])
Definition: math_geom.c:1104
float normal_poly_v3(float n[3], const float verts[][3], unsigned int nr)
Definition: math_geom.c:94
int isect_point_tri_v2(const float pt[2], const float v1[2], const float v2[2], const float v3[2])
Definition: math_geom.c:1595
bool is_poly_convex_v2(const float verts[][2], unsigned int nr)
Definition: math_geom.c:6139
int isect_seg_seg_v2_point(const float v0[2], const float v1[2], const float v2[2], const float v3[2], float r_vi[2])
Definition: math_geom.c:1353
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:51
bool isect_axial_line_segment_tri_v3(const int axis, const float p1[3], const float p2[3], const float v0[3], const float v1[3], const float v2[3], float *r_lambda)
Definition: math_geom.c:2981
bool isect_line_segment_tri_v3(const float p1[3], const float p2[3], const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2])
Definition: math_geom.c:1645
float area_quad_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition: math_geom.c:100
float area_poly_v2(const float verts[][2], unsigned int nr)
Definition: math_geom.c:204
bool clip_segment_v3_plane_n(const float p1[3], const float p2[3], const float plane_array[][4], const int plane_tot, float r_p1[3], float r_p2[3])
Definition: math_geom.c:3679
void interp_weights_poly_v3(float *w, float v[][3], const int n, const float co[3])
Definition: math_geom.c:4340
float dist_to_line_v2(const float p[2], const float l1[2], const float l2[2])
Definition: math_geom.c:332
void plane_to_point_vector_v3_normalized(const float plane[4], float r_plane_co[3], float r_plane_no[3])
Definition: math_geom.c:261
int isect_aabb_planes_v3(const float(*planes)[4], const int totplane, const float bbmin[3], const float bbmax[3])
Definition: math_geom.c:2766
float dist_squared_to_plane3_v3(const float pt[3], const float plane[3])
Definition: math_geom.c:456
void interp_bilinear_quad_v3(float data[4][3], float u, float v, float res[3])
Definition: math_geom.c:4766
bool isect_point_planes_v3_negated(const float(*planes)[4], const int totplane, const float p[3])
Definition: math_geom.c:2169
bool isect_point_tri_prism_v3(const float p[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:3589
void map_to_plane_axis_angle_v2_v3v3fl(float r_co[2], const float co[3], const float axis[3], const float angle)
Definition: math_geom.c:5267
bool isect_ray_plane_v3(const float ray_origin[3], const float ray_direction[3], const float plane[4], float *r_lambda, const bool clip)
Definition: math_geom.c:1808
float volume_tetrahedron_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition: math_geom.c:274
float dist_squared_to_line_segment_v2(const float p[2], const float l1[2], const float l2[2])
Definition: math_geom.c:338
void box_minmax_bounds_m4(float min[3], float max[3], float boundbox[2][3], float mat[4][4])
Definition: math_geom.c:5198
bool isect_point_planes_v3(float(*planes)[4], int totplane, const float p[3])
Definition: math_geom.c:2152
float dist_signed_squared_to_corner_v3v3v3(const float p[3], const float v1[3], const float v2[3], const float v3[3], const float axis_ref[3])
Definition: math_geom.c:543
static int left
bool isfinite(uchar)
Definition: image.cpp:44
static unsigned c
Definition: RandGen.cpp:97
static unsigned a[3]
Definition: RandGen.cpp:92
static void area(int d1, int d2, int e1, int e2, float weights[2])
static double epsilon
const btScalar eps
Definition: poly34.cpp:11
return ret
#define min(a, b)
Definition: sort.c:51
double dir[2]
Definition: math_geom.c:4291
double len
Definition: math_geom.c:4291
float dir[3]
Definition: math_geom.c:4287
float len
Definition: math_geom.c:4287
float max
__forceinline avxf cross(const avxf &a, const avxf &b)
Definition: util_avxf.h:119
ccl_device_inline float xor_signmask(float x, int y)
Definition: util_math.h:675
ccl_device_inline float dot(const float2 &a, const float2 &b)
ccl_device_inline float2 fabs(const float2 &a)
#define dot3(a, b)
uint len