Blender V4.3
GeomUtils.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009-2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10#include "GeomUtils.h"
11
12#include "BLI_sys_types.h"
13
15
16// This internal procedure is defined below.
17bool intersect2dSegPoly(Vec2r *seg, Vec2r *poly, uint n);
18
19bool intersect2dSeg2dArea(const Vec2r &min, const Vec2r &max, const Vec2r &A, const Vec2r &B)
20{
21 Vec2r seg[2];
22 seg[0] = A;
23 seg[1] = B;
24
25 Vec2r poly[5];
26 poly[0][0] = min[0];
27 poly[0][1] = min[1];
28 poly[1][0] = max[0];
29 poly[1][1] = min[1];
30 poly[2][0] = max[0];
31 poly[2][1] = max[1];
32 poly[3][0] = min[0];
33 poly[3][1] = max[1];
34 poly[4][0] = min[0];
35 poly[4][1] = min[1];
36
37 return intersect2dSegPoly(seg, poly, 4);
38}
39
40bool include2dSeg2dArea(const Vec2r &min, const Vec2r &max, const Vec2r &A, const Vec2r &B)
41{
42 if ((((max[0] > A[0]) && (A[0] > min[0])) && ((max[0] > B[0]) && (B[0] > min[0]))) &&
43 (((max[1] > A[1]) && (A[1] > min[1])) && ((max[1] > B[1]) && (B[1] > min[1]))))
44 {
45 return true;
46 }
47 return false;
48}
49
51 const Vec2r &p1, const Vec2r &p2, const Vec2r &p3, const Vec2r &p4, Vec2r &res)
52{
53 real a1, a2, b1, b2, c1, c2; // Coefficients of line eqns
54 real r1, r2, r3, r4; // 'Sign' values
55 real denom, num; // Intermediate values
56
57 // Compute a1, b1, c1, where line joining points p1 and p2 is "a1 x + b1 y + c1 = 0".
58 a1 = p2[1] - p1[1];
59 b1 = p1[0] - p2[0];
60 c1 = p2[0] * p1[1] - p1[0] * p2[1];
61
62 // Compute r3 and r4.
63 r3 = a1 * p3[0] + b1 * p3[1] + c1;
64 r4 = a1 * p4[0] + b1 * p4[1] + c1;
65
66 // Check signs of r3 and r4. If both point 3 and point 4 lie on same side of line 1,
67 // the line segments do not intersect.
68 if (r3 != 0 && r4 != 0 && r3 * r4 > 0.0) {
69 return DONT_INTERSECT;
70 }
71
72 // Compute a2, b2, c2
73 a2 = p4[1] - p3[1];
74 b2 = p3[0] - p4[0];
75 c2 = p4[0] * p3[1] - p3[0] * p4[1];
76
77 // Compute r1 and r2
78 r1 = a2 * p1[0] + b2 * p1[1] + c2;
79 r2 = a2 * p2[0] + b2 * p2[1] + c2;
80
81 // Check signs of r1 and r2. If both point 1 and point 2 lie on same side of second line
82 // segment, the line segments do not intersect.
83 if (r1 != 0 && r2 != 0 && r1 * r2 > 0.0) {
84 return DONT_INTERSECT;
85 }
86
87 // Line segments intersect: compute intersection point.
88 denom = a1 * b2 - a2 * b1;
89 if (fabs(denom) < M_EPSILON) {
90 return COLINEAR;
91 }
92
93 num = b1 * c2 - b2 * c1;
94 res[0] = num / denom;
95
96 num = a2 * c1 - a1 * c2;
97 res[1] = num / denom;
98
99 return DO_INTERSECT;
100}
101
103 const Vec2r &p1, const Vec2r &p2, const Vec2r &p3, const Vec2r &p4, Vec2r &res)
104{
105 real a1, a2, b1, b2, c1, c2; // Coefficients of line eqns
106 real denom, num; // Intermediate values
107
108 // Compute a1, b1, c1, where line joining points p1 and p2 is "a1 x + b1 y + c1 = 0".
109 a1 = p2[1] - p1[1];
110 b1 = p1[0] - p2[0];
111 c1 = p2[0] * p1[1] - p1[0] * p2[1];
112
113 // Compute a2, b2, c2
114 a2 = p4[1] - p3[1];
115 b2 = p3[0] - p4[0];
116 c2 = p4[0] * p3[1] - p3[0] * p4[1];
117
118 // Line segments intersect: compute intersection point.
119 denom = a1 * b2 - a2 * b1;
120 if (fabs(denom) < M_EPSILON) {
121 return COLINEAR;
122 }
123
124 num = b1 * c2 - b2 * c1;
125 res[0] = num / denom;
126
127 num = a2 * c1 - a1 * c2;
128 res[1] = num / denom;
129
130 return DO_INTERSECT;
131}
132
134 const Vec2r &p2,
135 const Vec2r &p3,
136 const Vec2r &p4,
137 real &t,
138 real &u,
139 real epsilon)
140{
141 real a1, a2, b1, b2, c1, c2; // Coefficients of line eqns
142 real r1, r2, r3, r4; // 'Sign' values
143 real denom, num; // Intermediate values
144
145 // Compute a1, b1, c1, where line joining points p1 and p2 is "a1 x + b1 y + c1 = 0".
146 a1 = p2[1] - p1[1];
147 b1 = p1[0] - p2[0];
148 c1 = p2[0] * p1[1] - p1[0] * p2[1];
149
150 // Compute r3 and r4.
151 r3 = a1 * p3[0] + b1 * p3[1] + c1;
152 r4 = a1 * p4[0] + b1 * p4[1] + c1;
153
154 // Check signs of r3 and r4. If both point 3 and point 4 lie on same side of line 1,
155 // the line segments do not intersect.
156 if (r3 != 0 && r4 != 0 && r3 * r4 > 0.0) {
157 return DONT_INTERSECT;
158 }
159
160 // Compute a2, b2, c2
161 a2 = p4[1] - p3[1];
162 b2 = p3[0] - p4[0];
163 c2 = p4[0] * p3[1] - p3[0] * p4[1];
164
165 // Compute r1 and r2
166 r1 = a2 * p1[0] + b2 * p1[1] + c2;
167 r2 = a2 * p2[0] + b2 * p2[1] + c2;
168
169 // Check signs of r1 and r2. If both point 1 and point 2 lie on same side of second line
170 // segment, the line segments do not intersect.
171 if (r1 != 0 && r2 != 0 && r1 * r2 > 0.0) {
172 return DONT_INTERSECT;
173 }
174
175 // Line segments intersect: compute intersection point.
176 denom = a1 * b2 - a2 * b1;
177 if (fabs(denom) < epsilon) {
178 return COLINEAR;
179 }
180
181 real d1, e1;
182
183 d1 = p1[1] - p3[1];
184 e1 = p1[0] - p3[0];
185
186 num = -b2 * d1 - a2 * e1;
187 t = num / denom;
188
189 num = -b1 * d1 - a1 * e1;
190 u = num / denom;
191
192 return DO_INTERSECT;
193}
194
195// AABB-triangle overlap test code by Tomas Akenine-Möller
196// Function: int triBoxOverlap(real boxcenter[3], real boxhalfsize[3],real triverts[3][3]);
197// History:
198// 2001-03-05: released the code in its first version
199// 2001-06-18: changed the order of the tests, faster
200//
201// Acknowledgement: Many thanks to Pierre Terdiman for suggestions and discussions on how to
202// optimize code. Thanks to David Hunt for finding a ">="-bug!
203
204#define X 0
205#define Y 1
206#define Z 2
207
208#define FINDMINMAX(x0, x1, x2, min, max) \
209 { \
210 min = max = x0; \
211 if (x1 < min) { \
212 min = x1; \
213 } \
214 if (x1 > max) { \
215 max = x1; \
216 } \
217 if (x2 < min) { \
218 min = x2; \
219 } \
220 if (x2 > max) { \
221 max = x2; \
222 } \
223 } \
224 (void)0
225
226//======================== X-tests ========================//
227#define AXISTEST_X01(a, b, fa, fb) \
228 { \
229 p0 = a * v0[Y] - b * v0[Z]; \
230 p2 = a * v2[Y] - b * v2[Z]; \
231 if (p0 < p2) { \
232 min = p0; \
233 max = p2; \
234 } \
235 else { \
236 min = p2; \
237 max = p0; \
238 } \
239 rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; \
240 if (min > rad || max < -rad) { \
241 return 0; \
242 } \
243 } \
244 (void)0
245
246#define AXISTEST_X2(a, b, fa, fb) \
247 { \
248 p0 = a * v0[Y] - b * v0[Z]; \
249 p1 = a * v1[Y] - b * v1[Z]; \
250 if (p0 < p1) { \
251 min = p0; \
252 max = p1; \
253 } \
254 else { \
255 min = p1; \
256 max = p0; \
257 } \
258 rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; \
259 if (min > rad || max < -rad) { \
260 return 0; \
261 } \
262 } \
263 (void)0
264
265//======================== Y-tests ========================//
266#define AXISTEST_Y02(a, b, fa, fb) \
267 { \
268 p0 = -a * v0[X] + b * v0[Z]; \
269 p2 = -a * v2[X] + b * v2[Z]; \
270 if (p0 < p2) { \
271 min = p0; \
272 max = p2; \
273 } \
274 else { \
275 min = p2; \
276 max = p0; \
277 } \
278 rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; \
279 if (min > rad || max < -rad) { \
280 return 0; \
281 } \
282 } \
283 (void)0
284
285#define AXISTEST_Y1(a, b, fa, fb) \
286 { \
287 p0 = -a * v0[X] + b * v0[Z]; \
288 p1 = -a * v1[X] + b * v1[Z]; \
289 if (p0 < p1) { \
290 min = p0; \
291 max = p1; \
292 } \
293 else { \
294 min = p1; \
295 max = p0; \
296 } \
297 rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; \
298 if (min > rad || max < -rad) { \
299 return 0; \
300 } \
301 } \
302 (void)0
303
304//======================== Z-tests ========================//
305#define AXISTEST_Z12(a, b, fa, fb) \
306 { \
307 p1 = a * v1[X] - b * v1[Y]; \
308 p2 = a * v2[X] - b * v2[Y]; \
309 if (p2 < p1) { \
310 min = p2; \
311 max = p1; \
312 } \
313 else { \
314 min = p1; \
315 max = p2; \
316 } \
317 rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; \
318 if (min > rad || max < -rad) { \
319 return 0; \
320 } \
321 } \
322 (void)0
323
324#define AXISTEST_Z0(a, b, fa, fb) \
325 { \
326 p0 = a * v0[X] - b * v0[Y]; \
327 p1 = a * v1[X] - b * v1[Y]; \
328 if (p0 < p1) { \
329 min = p0; \
330 max = p1; \
331 } \
332 else { \
333 min = p1; \
334 max = p0; \
335 } \
336 rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; \
337 if (min > rad || max < -rad) { \
338 return 0; \
339 } \
340 } \
341 (void)0
342
343// This internal procedure is defined below.
344bool overlapPlaneBox(const Vec3r &normal, const real d, const Vec3r &maxbox);
345
346bool overlapTriangleBox(const Vec3r &boxcenter, const Vec3r &boxhalfsize, const Vec3r triverts[3])
347{
348 /* Use separating axis theorem to test overlap between triangle and box need to test for overlap
349 * in these directions:
350 *
351 * 1) The {x,y,z}-directions
352 * (actually, since we use the AABB of the triangle we do not even need to test these).
353 * 2) Normal of the triangle.
354 * 3) `crossproduct(edge from tri, {x,y,z}-directin)` this gives 3x3=9 more tests.
355 *
356 * Adapted from Tomas Akenine-Möller code. */
357
358 Vec3r v0, v1, v2, normal, e0, e1, e2;
359 real min, max, d, p0, p1, p2, rad, fex, fey, fez;
360
361 // This is the fastest branch on Sun
362 // move everything so that the boxcenter is in (0, 0, 0)
363 v0 = triverts[0] - boxcenter;
364 v1 = triverts[1] - boxcenter;
365 v2 = triverts[2] - boxcenter;
366
367 // compute triangle edges
368 e0 = v1 - v0;
369 e1 = v2 - v1;
370 e2 = v0 - v2;
371
372 // Bullet 3:
373 // Do the 9 tests first (this was faster)
374 fex = fabs(e0[X]);
375 fey = fabs(e0[Y]);
376 fez = fabs(e0[Z]);
377 AXISTEST_X01(e0[Z], e0[Y], fez, fey);
378 AXISTEST_Y02(e0[Z], e0[X], fez, fex);
379 AXISTEST_Z12(e0[Y], e0[X], fey, fex);
380
381 fex = fabs(e1[X]);
382 fey = fabs(e1[Y]);
383 fez = fabs(e1[Z]);
384 AXISTEST_X01(e1[Z], e1[Y], fez, fey);
385 AXISTEST_Y02(e1[Z], e1[X], fez, fex);
386 AXISTEST_Z0(e1[Y], e1[X], fey, fex);
387
388 fex = fabs(e2[X]);
389 fey = fabs(e2[Y]);
390 fez = fabs(e2[Z]);
391 AXISTEST_X2(e2[Z], e2[Y], fez, fey);
392 AXISTEST_Y1(e2[Z], e2[X], fez, fex);
393 AXISTEST_Z12(e2[Y], e2[X], fey, fex);
394
395 // Bullet 1:
396 // first test overlap in the {x,y,z}-directions
397 // find min, max of the triangle each direction, and test for overlap in that direction -- this
398 // is equivalent to testing a minimal AABB around the triangle against the AABB
399
400 // test in X-direction
401 FINDMINMAX(v0[X], v1[X], v2[X], min, max);
402 if (min > boxhalfsize[X] || max < -boxhalfsize[X]) {
403 return false;
404 }
405
406 // test in Y-direction
407 FINDMINMAX(v0[Y], v1[Y], v2[Y], min, max);
408 if (min > boxhalfsize[Y] || max < -boxhalfsize[Y]) {
409 return false;
410 }
411
412 // test in Z-direction
413 FINDMINMAX(v0[Z], v1[Z], v2[Z], min, max);
414 if (min > boxhalfsize[Z] || max < -boxhalfsize[Z]) {
415 return false;
416 }
417
418 // Bullet 2:
419 // test if the box intersects the plane of the triangle
420 // compute plane equation of triangle: normal * x + d = 0
421 normal = e0 ^ e1;
422 d = -(normal * v0); // plane eq: normal.x + d = 0
423 if (!overlapPlaneBox(normal, d, boxhalfsize)) {
424 return false;
425 }
426
427 return true; // box and triangle overlaps
428}
429
431 const Vec3r &dir,
432 const Vec3r &v0,
433 const Vec3r &v1,
434 const Vec3r &v2,
435 real &t,
436 real &u,
437 real &v,
438 const real epsilon)
439{
440 /* Fast, Minimum Storage Ray-Triangle Intersection.
441 * Adapted from Tomas Möller and Ben Trumbore code.
442 *
443 * Tomas Möller, Prosolvia Clarus AB, Sweden, <tompa@clarus.se>.
444 * Ben Trumbore, Cornell University, Ithaca, New York <wbt@graphics.cornell.edu>. */
445
446 Vec3r edge1, edge2, tvec, pvec, qvec;
447 real det, inv_det;
448
449 // find vectors for two edges sharing v0
450 edge1 = v1 - v0;
451 edge2 = v2 - v0;
452
453 // begin calculating determinant - also used to calculate U parameter
454 pvec = dir ^ edge2;
455
456 // if determinant is near zero, ray lies in plane of triangle
457 det = edge1 * pvec;
458
459 // calculate distance from v0 to ray origin
460 tvec = orig - v0;
461 inv_det = 1.0 / det;
462
463 qvec = tvec ^ edge1;
464
465 if (det > epsilon) {
466 u = tvec * pvec;
467 if (u < 0.0 || u > det) {
468 return false;
469 }
470
471 // calculate V parameter and test bounds
472 v = dir * qvec;
473 if (v < 0.0 || u + v > det) {
474 return false;
475 }
476 }
477 else if (det < -epsilon) {
478 // calculate U parameter and test bounds
479 u = tvec * pvec;
480 if (u > 0.0 || u < det) {
481 return false;
482 }
483
484 // calculate V parameter and test bounds
485 v = dir * qvec;
486 if (v > 0.0 || u + v < det) {
487 return false;
488 }
489 }
490 else {
491 return false; // ray is parallel to the plane of the triangle
492 }
493
494 u *= inv_det;
495 v *= inv_det;
496 t = (edge2 * qvec) * inv_det;
497
498 return true;
499}
500
502 const Vec3r &dir,
503 const Vec3r &norm,
504 const real d,
505 real &t,
506 const real epsilon)
507{
508 /* Intersection between plane and ray, adapted from Graphics Gems, Didier Badouel
509 * The plane is represented by a set of points P implicitly defined as `dot(norm, P) + d = 0`.
510 * The ray is represented as `r(t) = orig + dir * t`. */
511
512 real denom = norm * dir;
513
514 if (fabs(denom) <= epsilon) { // plane and ray are parallel
515 if (fabs((norm * orig) + d) <= epsilon) {
516 return COINCIDENT; // plane and ray are coincident
517 }
518
519 return COLINEAR;
520 }
521
522 t = -(d + (norm * orig)) / denom;
523
524 if (t < 0.0f) {
525 return DONT_INTERSECT;
526 }
527
528 return DO_INTERSECT;
529}
530
531bool intersectRayBBox(const Vec3r &orig,
532 const Vec3r &dir, // ray origin and direction
533 const Vec3r &boxMin,
534 const Vec3r &boxMax, // the bbox
535 real t0,
536 real t1,
537 real &tmin, // I0 = orig + tmin * dir is the first intersection
538 real &tmax, // I1 = orig + tmax * dir is the second intersection
539 real /*epsilon*/)
540{
541 float tymin, tymax, tzmin, tzmax;
542 Vec3r inv_direction(1.0 / dir[0], 1.0 / dir[1], 1.0 / dir[2]);
543 int sign[3];
544 sign[0] = (inv_direction.x() < 0);
545 sign[1] = (inv_direction.y() < 0);
546 sign[2] = (inv_direction.z() < 0);
547
548 Vec3r bounds[2];
549 bounds[0] = boxMin;
550 bounds[1] = boxMax;
551
552 tmin = (bounds[sign[0]].x() - orig.x()) * inv_direction.x();
553 tmax = (bounds[1 - sign[0]].x() - orig.x()) * inv_direction.x();
554 tymin = (bounds[sign[1]].y() - orig.y()) * inv_direction.y();
555 tymax = (bounds[1 - sign[1]].y() - orig.y()) * inv_direction.y();
556 if ((tmin > tymax) || (tymin > tmax)) {
557 return false;
558 }
559 if (tymin > tmin) {
560 tmin = tymin;
561 }
562 if (tymax < tmax) {
563 tmax = tymax;
564 }
565 tzmin = (bounds[sign[2]].z() - orig.z()) * inv_direction.z();
566 tzmax = (bounds[1 - sign[2]].z() - orig.z()) * inv_direction.z();
567 if ((tmin > tzmax) || (tzmin > tmax)) {
568 return false;
569 }
570 if (tzmin > tmin) {
571 tmin = tzmin;
572 }
573 if (tzmax < tmax) {
574 tmax = tzmax;
575 }
576 return ((tmin < t1) && (tmax > t0));
577}
578
579// Checks whether 3D points p lies inside or outside of the triangle ABC
580bool includePointTriangle(const Vec3r &P, const Vec3r &A, const Vec3r &B, const Vec3r &C)
581{
582 Vec3r AB(B - A);
583 Vec3r BC(C - B);
584 Vec3r CA(A - C);
585 Vec3r AP(P - A);
586 Vec3r BP(P - B);
587 Vec3r CP(P - C);
588
589 Vec3r N(AB ^ BC); // triangle's normal
590
591 N.normalize();
592
593 Vec3r J(AB ^ AP), K(BC ^ BP), L(CA ^ CP);
594 J.normalize();
595 K.normalize();
596 L.normalize();
597
598 if (J * N < 0) {
599 return false; // on the right of AB
600 }
601
602 if (K * N < 0) {
603 return false; // on the right of BC
604 }
605
606 if (L * N < 0) {
607 return false; // on the right of CA
608 }
609
610 return true;
611}
612
613void transformVertex(const Vec3r &vert, const Matrix44r &matrix, Vec3r &res)
614{
615 HVec3r hvert(vert), res_tmp;
616 real scale;
617 for (uint j = 0; j < 4; j++) {
618 scale = hvert[j];
619 for (uint i = 0; i < 4; i++) {
620 res_tmp[i] += matrix(i, j) * scale;
621 }
622 }
623
624 res[0] = res_tmp.x();
625 res[1] = res_tmp.y();
626 res[2] = res_tmp.z();
627}
628
629void transformVertices(const vector<Vec3r> &vertices, const Matrix44r &trans, vector<Vec3r> &res)
630{
631 size_t i;
632 res.resize(vertices.size());
633 for (i = 0; i < vertices.size(); i++) {
634 transformVertex(vertices[i], trans, res[i]);
635 }
636}
637
638Vec3r rotateVector(const Matrix44r &mat, const Vec3r &v)
639{
640 Vec3r res;
641 for (uint i = 0; i < 3; i++) {
642 res[i] = 0;
643 for (uint j = 0; j < 3; j++) {
644 res[i] += mat(i, j) * v[j];
645 }
646 }
647 res.normalize();
648 return res;
649}
650
651// This internal procedure is defined below.
652void fromCoordAToCoordB(const Vec3r &p, Vec3r &q, const real transform[4][4]);
653
654void fromWorldToCamera(const Vec3r &p, Vec3r &q, const real model_view_matrix[4][4])
655{
656 fromCoordAToCoordB(p, q, model_view_matrix);
657}
658
659void fromCameraToRetina(const Vec3r &p, Vec3r &q, const real projection_matrix[4][4])
660{
661 fromCoordAToCoordB(p, q, projection_matrix);
662}
663
664void fromRetinaToImage(const Vec3r &p, Vec3r &q, const int viewport[4])
665{
666 // winX:
667 q[0] = viewport[0] + viewport[2] * (p[0] + 1.0) / 2.0;
668
669 // winY:
670 q[1] = viewport[1] + viewport[3] * (p[1] + 1.0) / 2.0;
671
672 // winZ:
673 q[2] = (p[2] + 1.0) / 2.0;
674}
675
677 Vec3r &q,
678 const real model_view_matrix[4][4],
679 const real projection_matrix[4][4],
680 const int viewport[4])
681{
682 Vec3r p1, p2;
683 fromWorldToCamera(p, p1, model_view_matrix);
684 fromCameraToRetina(p1, p2, projection_matrix);
685 fromRetinaToImage(p2, q, viewport);
686 q[2] = p1[2];
687}
688
689void fromWorldToImage(const Vec3r &p, Vec3r &q, const real transform[4][4], const int viewport[4])
690{
691 fromCoordAToCoordB(p, q, transform);
692
693 // winX:
694 q[0] = viewport[0] + viewport[2] * (q[0] + 1.0) / 2.0;
695
696 // winY:
697 q[1] = viewport[1] + viewport[3] * (q[1] + 1.0) / 2.0;
698}
699
700void fromImageToRetina(const Vec3r &p, Vec3r &q, const int viewport[4])
701{
702 q = p;
703 q[0] = 2.0 * (q[0] - viewport[0]) / viewport[2] - 1.0;
704 q[1] = 2.0 * (q[1] - viewport[1]) / viewport[3] - 1.0;
705}
706
707void fromRetinaToCamera(const Vec3r &p, Vec3r &q, real focal, const real projection_matrix[4][4])
708{
709 if (projection_matrix[3][3] == 0.0) { // perspective
710 q[0] = (-p[0] * focal) / projection_matrix[0][0];
711 q[1] = (-p[1] * focal) / projection_matrix[1][1];
712 q[2] = focal;
713 }
714 else { // orthogonal
715 q[0] = p[0] / projection_matrix[0][0];
716 q[1] = p[1] / projection_matrix[1][1];
717 q[2] = focal;
718 }
719}
720
721void fromCameraToWorld(const Vec3r &p, Vec3r &q, const real model_view_matrix[4][4])
722{
723 real translation[3] = {
724 model_view_matrix[0][3],
725 model_view_matrix[1][3],
726 model_view_matrix[2][3],
727 };
728 for (ushort i = 0; i < 3; i++) {
729 q[i] = 0.0;
730 for (ushort j = 0; j < 3; j++) {
731 q[i] += model_view_matrix[j][i] * (p[j] - translation[j]);
732 }
733 }
734}
735
736//
737// Internal code
738//
740
741// Copyright 2001, softSurfer (www.softsurfer.com)
742// This code may be freely used and modified for any purpose providing that this copyright notice
743// is included with it. SoftSurfer makes no warranty for this code, and cannot be held liable for
744// any real or imagined damage resulting from its use. Users of this code must verify correctness
745// for their application.
746
747#define PERP(u, v) ((u)[0] * (v)[1] - (u)[1] * (v)[0]) // 2D perp product
748
749inline bool intersect2dSegPoly(Vec2r *seg, Vec2r *poly, uint n)
750{
751 if (seg[0] == seg[1]) {
752 return false;
753 }
754
755 real tE = 0; // the maximum entering segment parameter
756 real tL = 1; // the minimum leaving segment parameter
757 real t, N, D; // intersect parameter t = N / D
758 Vec2r dseg = seg[1] - seg[0]; // the segment direction vector
759 Vec2r e; // edge vector
760
761 for (uint i = 0; i < n; i++) { // process polygon edge poly[i]poly[i+1]
762 e = poly[i + 1] - poly[i];
763 N = PERP(e, seg[0] - poly[i]);
764 D = -PERP(e, dseg);
765 if (fabs(D) < M_EPSILON) {
766 if (N < 0) {
767 return false;
768 }
769
770 continue;
771 }
772
773 t = N / D;
774 if (D < 0) { // segment seg is entering across this edge
775 if (t > tE) { // new max tE
776 tE = t;
777 if (tE > tL) { // seg enters after leaving polygon
778 return false;
779 }
780 }
781 }
782 else { // segment seg is leaving across this edge
783 if (t < tL) { // new min tL
784 tL = t;
785 if (tL < tE) { // seg leaves before entering polygon
786 return false;
787 }
788 }
789 }
790 }
791
792 // tE <= tL implies that there is a valid intersection subsegment
793 return true;
794}
795
796inline bool overlapPlaneBox(const Vec3r &normal, const real d, const Vec3r &maxbox)
797{
798 Vec3r vmin, vmax;
799
800 for (uint q = X; q <= Z; q++) {
801 if (normal[q] > 0.0f) {
802 vmin[q] = -maxbox[q];
803 vmax[q] = maxbox[q];
804 }
805 else {
806 vmin[q] = maxbox[q];
807 vmax[q] = -maxbox[q];
808 }
809 }
810 if ((normal * vmin) + d > 0.0f) {
811 return false;
812 }
813 if ((normal * vmax) + d >= 0.0f) {
814 return true;
815 }
816 return false;
817}
818
819inline void fromCoordAToCoordB(const Vec3r &p, Vec3r &q, const real transform[4][4])
820{
821 HVec3r hp(p);
822 HVec3r hq(0, 0, 0, 0);
823
824 for (uint i = 0; i < 4; i++) {
825 for (uint j = 0; j < 4; j++) {
826 hq[i] += transform[i][j] * hp[j];
827 }
828 }
829
830 if (hq[3] == 0) {
831 q = p;
832 return;
833 }
834
835 for (uint k = 0; k < 3; k++) {
836 q[k] = hq[k] / hq[3];
837 }
838}
839
840} // namespace Freestyle::GeomUtils
#define D
unsigned short ushort
unsigned int uint
#define K(key)
#define X
#define AXISTEST_Y02(a, b, fa, fb)
#define FINDMINMAX(x0, x1, x2, min, max)
#define AXISTEST_Z12(a, b, fa, fb)
#define Z
#define AXISTEST_Y1(a, b, fa, fb)
#define Y
#define AXISTEST_X2(a, b, fa, fb)
#define AXISTEST_X01(a, b, fa, fb)
#define PERP(u, v)
#define AXISTEST_Z0(a, b, fa, fb)
Various tools for geometry.
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define A
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition btDbvt.cpp:299
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
Definition btVector3.h:263
value_type z() const
Definition VecMat.h:456
value_type x() const
Definition VecMat.h:446
value_type y() const
Definition VecMat.h:451
value_type x() const
Definition VecMat.h:493
value_type z() const
Definition VecMat.h:513
value_type y() const
Definition VecMat.h:503
Vec< T, N > & normalize()
Definition VecMat.h:104
ccl_device_inline float2 fabs(const float2 a)
#define N
#define B
#define L
bool overlapPlaneBox(const Vec3r &normal, const real d, const Vec3r &maxbox)
void fromRetinaToImage(const Vec3r &p, Vec3r &q, const int viewport[4])
void fromWorldToImage(const Vec3r &p, Vec3r &q, const real model_view_matrix[4][4], const real projection_matrix[4][4], const int viewport[4])
bool overlapTriangleBox(const Vec3r &boxcenter, const Vec3r &boxhalfsize, const Vec3r triverts[3])
void transformVertex(const Vec3r &vert, const Matrix44r &matrix, Vec3r &res)
void fromWorldToCamera(const Vec3r &p, Vec3r &q, const real model_view_matrix[4][4])
intersection_test intersect2dSeg2dSegParametric(const Vec2r &p1, const Vec2r &p2, const Vec2r &p3, const Vec2r &p4, real &t, real &u, real epsilon)
bool intersect2dSeg2dArea(const Vec2r &min, const Vec2r &max, const Vec2r &A, const Vec2r &B)
Definition GeomUtils.cpp:19
intersection_test intersect2dSeg2dSeg(const Vec2r &p1, const Vec2r &p2, const Vec2r &p3, const Vec2r &p4, Vec2r &res)
Definition GeomUtils.cpp:50
void fromCoordAToCoordB(const Vec3r &p, Vec3r &q, const real transform[4][4])
void fromCameraToWorld(const Vec3r &p, Vec3r &q, const real model_view_matrix[4][4])
bool intersectRayTriangle(const Vec3r &orig, const Vec3r &dir, const Vec3r &v0, const Vec3r &v1, const Vec3r &v2, real &t, real &u, real &v, const real epsilon)
bool includePointTriangle(const Vec3r &P, const Vec3r &A, const Vec3r &B, const Vec3r &C)
void fromCameraToRetina(const Vec3r &p, Vec3r &q, const real projection_matrix[4][4])
void transformVertices(const vector< Vec3r > &vertices, const Matrix44r &trans, vector< Vec3r > &res)
bool intersect2dSegPoly(Vec2r *seg, Vec2r *poly, uint n)
bool intersectRayBBox(const Vec3r &orig, const Vec3r &dir, const Vec3r &boxMin, const Vec3r &boxMax, real t0, real t1, real &tmin, real &tmax, real)
bool include2dSeg2dArea(const Vec2r &min, const Vec2r &max, const Vec2r &A, const Vec2r &B)
Definition GeomUtils.cpp:40
intersection_test intersectRayPlane(const Vec3r &orig, const Vec3r &dir, const Vec3r &norm, const real d, real &t, const real epsilon)
void fromRetinaToCamera(const Vec3r &p, Vec3r &q, real focal, const real projection_matrix[4][4])
void fromImageToRetina(const Vec3r &p, Vec3r &q, const int viewport[4])
intersection_test intersect2dLine2dLine(const Vec2r &p1, const Vec2r &p2, const Vec2r &p3, const Vec2r &p4, Vec2r &res)
Vec3r rotateVector(const Matrix44r &mat, const Vec3r &v)
VecMat::Vec3< real > Vec3r
Definition Geom.h:30
static const real M_EPSILON
Definition Precision.h:17
double real
Definition Precision.h:14
#define min(a, b)
Definition sort.c:32
float max