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