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