Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/3rdparty/openexr/Imath/ImathBoxAlgo.h
16337 views
1
///////////////////////////////////////////////////////////////////////////
2
//
3
// Copyright (c) 2002-2010, Industrial Light & Magic, a division of Lucas
4
// Digital Ltd. LLC
5
//
6
// All rights reserved.
7
//
8
// Redistribution and use in source and binary forms, with or without
9
// modification, are permitted provided that the following conditions are
10
// met:
11
// * Redistributions of source code must retain the above copyright
12
// notice, this list of conditions and the following disclaimer.
13
// * Redistributions in binary form must reproduce the above
14
// copyright notice, this list of conditions and the following disclaimer
15
// in the documentation and/or other materials provided with the
16
// distribution.
17
// * Neither the name of Industrial Light & Magic nor the names of
18
// its contributors may be used to endorse or promote products derived
19
// from this software without specific prior written permission.
20
//
21
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
//
33
///////////////////////////////////////////////////////////////////////////
34
35
36
37
#ifndef INCLUDED_IMATHBOXALGO_H
38
#define INCLUDED_IMATHBOXALGO_H
39
40
41
//---------------------------------------------------------------------------
42
//
43
// This file contains algorithms applied to or in conjunction
44
// with bounding boxes (Imath::Box). These algorithms require
45
// more headers to compile. The assumption made is that these
46
// functions are called much less often than the basic box
47
// functions or these functions require more support classes.
48
//
49
// Contains:
50
//
51
// T clip<T>(const T& in, const Box<T>& box)
52
//
53
// Vec3<T> closestPointOnBox(const Vec3<T>&, const Box<Vec3<T>>& )
54
//
55
// Vec3<T> closestPointInBox(const Vec3<T>&, const Box<Vec3<T>>& )
56
//
57
// Box< Vec3<S> > transform(const Box<Vec3<S>>&, const Matrix44<T>&)
58
// Box< Vec3<S> > affineTransform(const Box<Vec3<S>>&, const Matrix44<T>&)
59
//
60
// void transform(const Box<Vec3<S>>&, const Matrix44<T>&, Box<V3ec3<S>>&)
61
// void affineTransform(const Box<Vec3<S>>&,
62
// const Matrix44<T>&,
63
// Box<V3ec3<S>>&)
64
//
65
// bool findEntryAndExitPoints(const Line<T> &line,
66
// const Box< Vec3<T> > &box,
67
// Vec3<T> &enterPoint,
68
// Vec3<T> &exitPoint)
69
//
70
// bool intersects(const Box<Vec3<T>> &box,
71
// const Line3<T> &ray,
72
// Vec3<T> intersectionPoint)
73
//
74
// bool intersects(const Box<Vec3<T>> &box, const Line3<T> &ray)
75
//
76
//---------------------------------------------------------------------------
77
78
#include "ImathBox.h"
79
#include "ImathMatrix.h"
80
#include "ImathLineAlgo.h"
81
#include "ImathPlane.h"
82
83
namespace Imath {
84
85
86
template <class T>
87
inline T
88
clip (const T &p, const Box<T> &box)
89
{
90
//
91
// Clip the coordinates of a point, p, against a box.
92
// The result, q, is the closest point to p that is inside the box.
93
//
94
95
T q;
96
97
for (int i = 0; i < int (box.min.dimensions()); i++)
98
{
99
if (p[i] < box.min[i])
100
q[i] = box.min[i];
101
else if (p[i] > box.max[i])
102
q[i] = box.max[i];
103
else
104
q[i] = p[i];
105
}
106
107
return q;
108
}
109
110
111
template <class T>
112
inline T
113
closestPointInBox (const T &p, const Box<T> &box)
114
{
115
return clip (p, box);
116
}
117
118
119
template <class T>
120
Vec3<T>
121
closestPointOnBox (const Vec3<T> &p, const Box< Vec3<T> > &box)
122
{
123
//
124
// Find the point, q, on the surface of
125
// the box, that is closest to point p.
126
//
127
// If the box is empty, return p.
128
//
129
130
if (box.isEmpty())
131
return p;
132
133
Vec3<T> q = closestPointInBox (p, box);
134
135
if (q == p)
136
{
137
Vec3<T> d1 = p - box.min;
138
Vec3<T> d2 = box.max - p;
139
140
Vec3<T> d ((d1.x < d2.x)? d1.x: d2.x,
141
(d1.y < d2.y)? d1.y: d2.y,
142
(d1.z < d2.z)? d1.z: d2.z);
143
144
if (d.x < d.y && d.x < d.z)
145
{
146
q.x = (d1.x < d2.x)? box.min.x: box.max.x;
147
}
148
else if (d.y < d.z)
149
{
150
q.y = (d1.y < d2.y)? box.min.y: box.max.y;
151
}
152
else
153
{
154
q.z = (d1.z < d2.z)? box.min.z: box.max.z;
155
}
156
}
157
158
return q;
159
}
160
161
162
template <class S, class T>
163
Box< Vec3<S> >
164
transform (const Box< Vec3<S> > &box, const Matrix44<T> &m)
165
{
166
//
167
// Transform a 3D box by a matrix, and compute a new box that
168
// tightly encloses the transformed box.
169
//
170
// If m is an affine transform, then we use James Arvo's fast
171
// method as described in "Graphics Gems", Academic Press, 1990,
172
// pp. 548-550.
173
//
174
175
//
176
// A transformed empty box is still empty, and a transformed infinite box
177
// is still infinite
178
//
179
180
if (box.isEmpty() || box.isInfinite())
181
return box;
182
183
//
184
// If the last column of m is (0 0 0 1) then m is an affine
185
// transform, and we use the fast Graphics Gems trick.
186
//
187
188
if (m[0][3] == 0 && m[1][3] == 0 && m[2][3] == 0 && m[3][3] == 1)
189
{
190
Box< Vec3<S> > newBox;
191
192
for (int i = 0; i < 3; i++)
193
{
194
newBox.min[i] = newBox.max[i] = (S) m[3][i];
195
196
for (int j = 0; j < 3; j++)
197
{
198
S a, b;
199
200
a = (S) m[j][i] * box.min[j];
201
b = (S) m[j][i] * box.max[j];
202
203
if (a < b)
204
{
205
newBox.min[i] += a;
206
newBox.max[i] += b;
207
}
208
else
209
{
210
newBox.min[i] += b;
211
newBox.max[i] += a;
212
}
213
}
214
}
215
216
return newBox;
217
}
218
219
//
220
// M is a projection matrix. Do things the naive way:
221
// Transform the eight corners of the box, and find an
222
// axis-parallel box that encloses the transformed corners.
223
//
224
225
Vec3<S> points[8];
226
227
points[0][0] = points[1][0] = points[2][0] = points[3][0] = box.min[0];
228
points[4][0] = points[5][0] = points[6][0] = points[7][0] = box.max[0];
229
230
points[0][1] = points[1][1] = points[4][1] = points[5][1] = box.min[1];
231
points[2][1] = points[3][1] = points[6][1] = points[7][1] = box.max[1];
232
233
points[0][2] = points[2][2] = points[4][2] = points[6][2] = box.min[2];
234
points[1][2] = points[3][2] = points[5][2] = points[7][2] = box.max[2];
235
236
Box< Vec3<S> > newBox;
237
238
for (int i = 0; i < 8; i++)
239
newBox.extendBy (points[i] * m);
240
241
return newBox;
242
}
243
244
template <class S, class T>
245
void
246
transform (const Box< Vec3<S> > &box,
247
const Matrix44<T> &m,
248
Box< Vec3<S> > &result)
249
{
250
//
251
// Transform a 3D box by a matrix, and compute a new box that
252
// tightly encloses the transformed box.
253
//
254
// If m is an affine transform, then we use James Arvo's fast
255
// method as described in "Graphics Gems", Academic Press, 1990,
256
// pp. 548-550.
257
//
258
259
//
260
// A transformed empty box is still empty, and a transformed infinite
261
// box is still infinite
262
//
263
264
if (box.isEmpty() || box.isInfinite())
265
{
266
return;
267
}
268
269
//
270
// If the last column of m is (0 0 0 1) then m is an affine
271
// transform, and we use the fast Graphics Gems trick.
272
//
273
274
if (m[0][3] == 0 && m[1][3] == 0 && m[2][3] == 0 && m[3][3] == 1)
275
{
276
for (int i = 0; i < 3; i++)
277
{
278
result.min[i] = result.max[i] = (S) m[3][i];
279
280
for (int j = 0; j < 3; j++)
281
{
282
S a, b;
283
284
a = (S) m[j][i] * box.min[j];
285
b = (S) m[j][i] * box.max[j];
286
287
if (a < b)
288
{
289
result.min[i] += a;
290
result.max[i] += b;
291
}
292
else
293
{
294
result.min[i] += b;
295
result.max[i] += a;
296
}
297
}
298
}
299
300
return;
301
}
302
303
//
304
// M is a projection matrix. Do things the naive way:
305
// Transform the eight corners of the box, and find an
306
// axis-parallel box that encloses the transformed corners.
307
//
308
309
Vec3<S> points[8];
310
311
points[0][0] = points[1][0] = points[2][0] = points[3][0] = box.min[0];
312
points[4][0] = points[5][0] = points[6][0] = points[7][0] = box.max[0];
313
314
points[0][1] = points[1][1] = points[4][1] = points[5][1] = box.min[1];
315
points[2][1] = points[3][1] = points[6][1] = points[7][1] = box.max[1];
316
317
points[0][2] = points[2][2] = points[4][2] = points[6][2] = box.min[2];
318
points[1][2] = points[3][2] = points[5][2] = points[7][2] = box.max[2];
319
320
for (int i = 0; i < 8; i++)
321
result.extendBy (points[i] * m);
322
}
323
324
325
template <class S, class T>
326
Box< Vec3<S> >
327
affineTransform (const Box< Vec3<S> > &box, const Matrix44<T> &m)
328
{
329
//
330
// Transform a 3D box by a matrix whose rightmost column
331
// is (0 0 0 1), and compute a new box that tightly encloses
332
// the transformed box.
333
//
334
// As in the transform() function, above, we use James Arvo's
335
// fast method.
336
//
337
338
if (box.isEmpty() || box.isInfinite())
339
{
340
//
341
// A transformed empty or infinite box is still empty or infinite
342
//
343
344
return box;
345
}
346
347
Box< Vec3<S> > newBox;
348
349
for (int i = 0; i < 3; i++)
350
{
351
newBox.min[i] = newBox.max[i] = (S) m[3][i];
352
353
for (int j = 0; j < 3; j++)
354
{
355
S a, b;
356
357
a = (S) m[j][i] * box.min[j];
358
b = (S) m[j][i] * box.max[j];
359
360
if (a < b)
361
{
362
newBox.min[i] += a;
363
newBox.max[i] += b;
364
}
365
else
366
{
367
newBox.min[i] += b;
368
newBox.max[i] += a;
369
}
370
}
371
}
372
373
return newBox;
374
}
375
376
template <class S, class T>
377
void
378
affineTransform (const Box< Vec3<S> > &box,
379
const Matrix44<T> &m,
380
Box<Vec3<S> > &result)
381
{
382
//
383
// Transform a 3D box by a matrix whose rightmost column
384
// is (0 0 0 1), and compute a new box that tightly encloses
385
// the transformed box.
386
//
387
// As in the transform() function, above, we use James Arvo's
388
// fast method.
389
//
390
391
if (box.isEmpty())
392
{
393
//
394
// A transformed empty box is still empty
395
//
396
result.makeEmpty();
397
return;
398
}
399
400
if (box.isInfinite())
401
{
402
//
403
// A transformed infinite box is still infinite
404
//
405
result.makeInfinite();
406
return;
407
}
408
409
for (int i = 0; i < 3; i++)
410
{
411
result.min[i] = result.max[i] = (S) m[3][i];
412
413
for (int j = 0; j < 3; j++)
414
{
415
S a, b;
416
417
a = (S) m[j][i] * box.min[j];
418
b = (S) m[j][i] * box.max[j];
419
420
if (a < b)
421
{
422
result.min[i] += a;
423
result.max[i] += b;
424
}
425
else
426
{
427
result.min[i] += b;
428
result.max[i] += a;
429
}
430
}
431
}
432
}
433
434
435
template <class T>
436
bool
437
findEntryAndExitPoints (const Line3<T> &r,
438
const Box<Vec3<T> > &b,
439
Vec3<T> &entry,
440
Vec3<T> &exit)
441
{
442
//
443
// Compute the points where a ray, r, enters and exits a box, b:
444
//
445
// findEntryAndExitPoints() returns
446
//
447
// - true if the ray starts inside the box or if the
448
// ray starts outside and intersects the box
449
//
450
// - false otherwise (that is, if the ray does not
451
// intersect the box)
452
//
453
// The entry and exit points are
454
//
455
// - points on two of the faces of the box when
456
// findEntryAndExitPoints() returns true
457
// (The entry end exit points may be on either
458
// side of the ray's origin)
459
//
460
// - undefined when findEntryAndExitPoints()
461
// returns false
462
//
463
464
if (b.isEmpty())
465
{
466
//
467
// No ray intersects an empty box
468
//
469
470
return false;
471
}
472
473
//
474
// The following description assumes that the ray's origin is outside
475
// the box, but the code below works even if the origin is inside the
476
// box:
477
//
478
// Between one and three "frontfacing" sides of the box are oriented
479
// towards the ray's origin, and between one and three "backfacing"
480
// sides are oriented away from the ray's origin.
481
// We intersect the ray with the planes that contain the sides of the
482
// box, and compare the distances between the ray's origin and the
483
// ray-plane intersections. The ray intersects the box if the most
484
// distant frontfacing intersection is nearer than the nearest
485
// backfacing intersection. If the ray does intersect the box, then
486
// the most distant frontfacing ray-plane intersection is the entry
487
// point and the nearest backfacing ray-plane intersection is the
488
// exit point.
489
//
490
491
const T TMAX = limits<T>::max();
492
493
T tFrontMax = -TMAX;
494
T tBackMin = TMAX;
495
496
//
497
// Minimum and maximum X sides.
498
//
499
500
if (r.dir.x >= 0)
501
{
502
T d1 = b.max.x - r.pos.x;
503
T d2 = b.min.x - r.pos.x;
504
505
if (r.dir.x > 1 ||
506
(abs (d1) < TMAX * r.dir.x &&
507
abs (d2) < TMAX * r.dir.x))
508
{
509
T t1 = d1 / r.dir.x;
510
T t2 = d2 / r.dir.x;
511
512
if (tBackMin > t1)
513
{
514
tBackMin = t1;
515
516
exit.x = b.max.x;
517
exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y);
518
exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z);
519
}
520
521
if (tFrontMax < t2)
522
{
523
tFrontMax = t2;
524
525
entry.x = b.min.x;
526
entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y);
527
entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z);
528
}
529
}
530
else if (r.pos.x < b.min.x || r.pos.x > b.max.x)
531
{
532
return false;
533
}
534
}
535
else // r.dir.x < 0
536
{
537
T d1 = b.min.x - r.pos.x;
538
T d2 = b.max.x - r.pos.x;
539
540
if (r.dir.x < -1 ||
541
(abs (d1) < -TMAX * r.dir.x &&
542
abs (d2) < -TMAX * r.dir.x))
543
{
544
T t1 = d1 / r.dir.x;
545
T t2 = d2 / r.dir.x;
546
547
if (tBackMin > t1)
548
{
549
tBackMin = t1;
550
551
exit.x = b.min.x;
552
exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y);
553
exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z);
554
}
555
556
if (tFrontMax < t2)
557
{
558
tFrontMax = t2;
559
560
entry.x = b.max.x;
561
entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y);
562
entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z);
563
}
564
}
565
else if (r.pos.x < b.min.x || r.pos.x > b.max.x)
566
{
567
return false;
568
}
569
}
570
571
//
572
// Minimum and maximum Y sides.
573
//
574
575
if (r.dir.y >= 0)
576
{
577
T d1 = b.max.y - r.pos.y;
578
T d2 = b.min.y - r.pos.y;
579
580
if (r.dir.y > 1 ||
581
(abs (d1) < TMAX * r.dir.y &&
582
abs (d2) < TMAX * r.dir.y))
583
{
584
T t1 = d1 / r.dir.y;
585
T t2 = d2 / r.dir.y;
586
587
if (tBackMin > t1)
588
{
589
tBackMin = t1;
590
591
exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x);
592
exit.y = b.max.y;
593
exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z);
594
}
595
596
if (tFrontMax < t2)
597
{
598
tFrontMax = t2;
599
600
entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x);
601
entry.y = b.min.y;
602
entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z);
603
}
604
}
605
else if (r.pos.y < b.min.y || r.pos.y > b.max.y)
606
{
607
return false;
608
}
609
}
610
else // r.dir.y < 0
611
{
612
T d1 = b.min.y - r.pos.y;
613
T d2 = b.max.y - r.pos.y;
614
615
if (r.dir.y < -1 ||
616
(abs (d1) < -TMAX * r.dir.y &&
617
abs (d2) < -TMAX * r.dir.y))
618
{
619
T t1 = d1 / r.dir.y;
620
T t2 = d2 / r.dir.y;
621
622
if (tBackMin > t1)
623
{
624
tBackMin = t1;
625
626
exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x);
627
exit.y = b.min.y;
628
exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z);
629
}
630
631
if (tFrontMax < t2)
632
{
633
tFrontMax = t2;
634
635
entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x);
636
entry.y = b.max.y;
637
entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z);
638
}
639
}
640
else if (r.pos.y < b.min.y || r.pos.y > b.max.y)
641
{
642
return false;
643
}
644
}
645
646
//
647
// Minimum and maximum Z sides.
648
//
649
650
if (r.dir.z >= 0)
651
{
652
T d1 = b.max.z - r.pos.z;
653
T d2 = b.min.z - r.pos.z;
654
655
if (r.dir.z > 1 ||
656
(abs (d1) < TMAX * r.dir.z &&
657
abs (d2) < TMAX * r.dir.z))
658
{
659
T t1 = d1 / r.dir.z;
660
T t2 = d2 / r.dir.z;
661
662
if (tBackMin > t1)
663
{
664
tBackMin = t1;
665
666
exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x);
667
exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y);
668
exit.z = b.max.z;
669
}
670
671
if (tFrontMax < t2)
672
{
673
tFrontMax = t2;
674
675
entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x);
676
entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y);
677
entry.z = b.min.z;
678
}
679
}
680
else if (r.pos.z < b.min.z || r.pos.z > b.max.z)
681
{
682
return false;
683
}
684
}
685
else // r.dir.z < 0
686
{
687
T d1 = b.min.z - r.pos.z;
688
T d2 = b.max.z - r.pos.z;
689
690
if (r.dir.z < -1 ||
691
(abs (d1) < -TMAX * r.dir.z &&
692
abs (d2) < -TMAX * r.dir.z))
693
{
694
T t1 = d1 / r.dir.z;
695
T t2 = d2 / r.dir.z;
696
697
if (tBackMin > t1)
698
{
699
tBackMin = t1;
700
701
exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x);
702
exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y);
703
exit.z = b.min.z;
704
}
705
706
if (tFrontMax < t2)
707
{
708
tFrontMax = t2;
709
710
entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x);
711
entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y);
712
entry.z = b.max.z;
713
}
714
}
715
else if (r.pos.z < b.min.z || r.pos.z > b.max.z)
716
{
717
return false;
718
}
719
}
720
721
return tFrontMax <= tBackMin;
722
}
723
724
725
template<class T>
726
bool
727
intersects (const Box< Vec3<T> > &b, const Line3<T> &r, Vec3<T> &ip)
728
{
729
//
730
// Intersect a ray, r, with a box, b, and compute the intersection
731
// point, ip:
732
//
733
// intersect() returns
734
//
735
// - true if the ray starts inside the box or if the
736
// ray starts outside and intersects the box
737
//
738
// - false if the ray starts outside the box and intersects it,
739
// but the intersection is behind the ray's origin.
740
//
741
// - false if the ray starts outside and does not intersect it
742
//
743
// The intersection point is
744
//
745
// - the ray's origin if the ray starts inside the box
746
//
747
// - a point on one of the faces of the box if the ray
748
// starts outside the box
749
//
750
// - undefined when intersect() returns false
751
//
752
753
if (b.isEmpty())
754
{
755
//
756
// No ray intersects an empty box
757
//
758
759
return false;
760
}
761
762
if (b.intersects (r.pos))
763
{
764
//
765
// The ray starts inside the box
766
//
767
768
ip = r.pos;
769
return true;
770
}
771
772
//
773
// The ray starts outside the box. Between one and three "frontfacing"
774
// sides of the box are oriented towards the ray, and between one and
775
// three "backfacing" sides are oriented away from the ray.
776
// We intersect the ray with the planes that contain the sides of the
777
// box, and compare the distances between ray's origin and the ray-plane
778
// intersections.
779
// The ray intersects the box if the most distant frontfacing intersection
780
// is nearer than the nearest backfacing intersection. If the ray does
781
// intersect the box, then the most distant frontfacing ray-plane
782
// intersection is the ray-box intersection.
783
//
784
785
const T TMAX = limits<T>::max();
786
787
T tFrontMax = -1;
788
T tBackMin = TMAX;
789
790
//
791
// Minimum and maximum X sides.
792
//
793
794
if (r.dir.x > 0)
795
{
796
if (r.pos.x > b.max.x)
797
return false;
798
799
T d = b.max.x - r.pos.x;
800
801
if (r.dir.x > 1 || d < TMAX * r.dir.x)
802
{
803
T t = d / r.dir.x;
804
805
if (tBackMin > t)
806
tBackMin = t;
807
}
808
809
if (r.pos.x <= b.min.x)
810
{
811
T d = b.min.x - r.pos.x;
812
T t = (r.dir.x > 1 || d < TMAX * r.dir.x)? d / r.dir.x: TMAX;
813
814
if (tFrontMax < t)
815
{
816
tFrontMax = t;
817
818
ip.x = b.min.x;
819
ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y);
820
ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z);
821
}
822
}
823
}
824
else if (r.dir.x < 0)
825
{
826
if (r.pos.x < b.min.x)
827
return false;
828
829
T d = b.min.x - r.pos.x;
830
831
if (r.dir.x < -1 || d > TMAX * r.dir.x)
832
{
833
T t = d / r.dir.x;
834
835
if (tBackMin > t)
836
tBackMin = t;
837
}
838
839
if (r.pos.x >= b.max.x)
840
{
841
T d = b.max.x - r.pos.x;
842
T t = (r.dir.x < -1 || d > TMAX * r.dir.x)? d / r.dir.x: TMAX;
843
844
if (tFrontMax < t)
845
{
846
tFrontMax = t;
847
848
ip.x = b.max.x;
849
ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y);
850
ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z);
851
}
852
}
853
}
854
else // r.dir.x == 0
855
{
856
if (r.pos.x < b.min.x || r.pos.x > b.max.x)
857
return false;
858
}
859
860
//
861
// Minimum and maximum Y sides.
862
//
863
864
if (r.dir.y > 0)
865
{
866
if (r.pos.y > b.max.y)
867
return false;
868
869
T d = b.max.y - r.pos.y;
870
871
if (r.dir.y > 1 || d < TMAX * r.dir.y)
872
{
873
T t = d / r.dir.y;
874
875
if (tBackMin > t)
876
tBackMin = t;
877
}
878
879
if (r.pos.y <= b.min.y)
880
{
881
T d = b.min.y - r.pos.y;
882
T t = (r.dir.y > 1 || d < TMAX * r.dir.y)? d / r.dir.y: TMAX;
883
884
if (tFrontMax < t)
885
{
886
tFrontMax = t;
887
888
ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x);
889
ip.y = b.min.y;
890
ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z);
891
}
892
}
893
}
894
else if (r.dir.y < 0)
895
{
896
if (r.pos.y < b.min.y)
897
return false;
898
899
T d = b.min.y - r.pos.y;
900
901
if (r.dir.y < -1 || d > TMAX * r.dir.y)
902
{
903
T t = d / r.dir.y;
904
905
if (tBackMin > t)
906
tBackMin = t;
907
}
908
909
if (r.pos.y >= b.max.y)
910
{
911
T d = b.max.y - r.pos.y;
912
T t = (r.dir.y < -1 || d > TMAX * r.dir.y)? d / r.dir.y: TMAX;
913
914
if (tFrontMax < t)
915
{
916
tFrontMax = t;
917
918
ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x);
919
ip.y = b.max.y;
920
ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z);
921
}
922
}
923
}
924
else // r.dir.y == 0
925
{
926
if (r.pos.y < b.min.y || r.pos.y > b.max.y)
927
return false;
928
}
929
930
//
931
// Minimum and maximum Z sides.
932
//
933
934
if (r.dir.z > 0)
935
{
936
if (r.pos.z > b.max.z)
937
return false;
938
939
T d = b.max.z - r.pos.z;
940
941
if (r.dir.z > 1 || d < TMAX * r.dir.z)
942
{
943
T t = d / r.dir.z;
944
945
if (tBackMin > t)
946
tBackMin = t;
947
}
948
949
if (r.pos.z <= b.min.z)
950
{
951
T d = b.min.z - r.pos.z;
952
T t = (r.dir.z > 1 || d < TMAX * r.dir.z)? d / r.dir.z: TMAX;
953
954
if (tFrontMax < t)
955
{
956
tFrontMax = t;
957
958
ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x);
959
ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y);
960
ip.z = b.min.z;
961
}
962
}
963
}
964
else if (r.dir.z < 0)
965
{
966
if (r.pos.z < b.min.z)
967
return false;
968
969
T d = b.min.z - r.pos.z;
970
971
if (r.dir.z < -1 || d > TMAX * r.dir.z)
972
{
973
T t = d / r.dir.z;
974
975
if (tBackMin > t)
976
tBackMin = t;
977
}
978
979
if (r.pos.z >= b.max.z)
980
{
981
T d = b.max.z - r.pos.z;
982
T t = (r.dir.z < -1 || d > TMAX * r.dir.z)? d / r.dir.z: TMAX;
983
984
if (tFrontMax < t)
985
{
986
tFrontMax = t;
987
988
ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x);
989
ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y);
990
ip.z = b.max.z;
991
}
992
}
993
}
994
else // r.dir.z == 0
995
{
996
if (r.pos.z < b.min.z || r.pos.z > b.max.z)
997
return false;
998
}
999
1000
return tFrontMax <= tBackMin;
1001
}
1002
1003
1004
template<class T>
1005
bool
1006
intersects (const Box< Vec3<T> > &box, const Line3<T> &ray)
1007
{
1008
Vec3<T> ignored;
1009
return intersects (box, ray, ignored);
1010
}
1011
1012
1013
} // namespace Imath
1014
1015
#endif
1016
1017