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