[855] | 1 | /////////////////////////////////////////////////////////////////////////// |
---|
| 2 | // |
---|
| 3 | // Copyright (c) 2002, 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 | // void transform(Box<Vec3<T>>&, const Matrix44<T>&) |
---|
| 58 | // |
---|
| 59 | // bool findEntryAndExitPoints(const Line<T> &line, |
---|
| 60 | // const Box< Vec3<T> > &box, |
---|
| 61 | // Vec3<T> &enterPoint, |
---|
| 62 | // Vec3<T> &exitPoint) |
---|
| 63 | // |
---|
| 64 | // bool intersects(const Box<Vec3<T>> &box, |
---|
| 65 | // const Line3<T> &line, |
---|
| 66 | // Vec3<T> result) |
---|
| 67 | // |
---|
| 68 | // bool intersects(const Box<Vec3<T>> &box, const Line3<T> &line) |
---|
| 69 | // |
---|
| 70 | //--------------------------------------------------------------------------- |
---|
| 71 | |
---|
| 72 | #include <ImathBox.h> |
---|
| 73 | #include <ImathMatrix.h> |
---|
| 74 | #include <ImathLineAlgo.h> |
---|
| 75 | #include <ImathPlane.h> |
---|
| 76 | |
---|
| 77 | namespace Imath { |
---|
| 78 | |
---|
| 79 | |
---|
| 80 | template <class T> |
---|
| 81 | inline T clip(const T& in, const Box<T>& box) |
---|
| 82 | { |
---|
| 83 | // |
---|
| 84 | // Clip a point so that it lies inside the given bbox |
---|
| 85 | // |
---|
| 86 | |
---|
| 87 | T out; |
---|
| 88 | |
---|
| 89 | for (int i=0; i<(int)box.min.dimensions(); i++) |
---|
| 90 | { |
---|
| 91 | if (in[i] < box.min[i]) out[i] = box.min[i]; |
---|
| 92 | else if (in[i] > box.max[i]) out[i] = box.max[i]; |
---|
| 93 | else out[i] = in[i]; |
---|
| 94 | } |
---|
| 95 | |
---|
| 96 | return out; |
---|
| 97 | } |
---|
| 98 | |
---|
| 99 | |
---|
| 100 | // |
---|
| 101 | // Return p if p is inside the box. |
---|
| 102 | // |
---|
| 103 | |
---|
| 104 | template <class T> |
---|
| 105 | Vec3<T> |
---|
| 106 | closestPointInBox(const Vec3<T>& p, const Box< Vec3<T> >& box ) |
---|
| 107 | { |
---|
| 108 | Imath::V3f b; |
---|
| 109 | |
---|
| 110 | if (p.x < box.min.x) |
---|
| 111 | b.x = box.min.x; |
---|
| 112 | else if (p.x > box.max.x) |
---|
| 113 | b.x = box.max.x; |
---|
| 114 | else |
---|
| 115 | b.x = p.x; |
---|
| 116 | |
---|
| 117 | if (p.y < box.min.y) |
---|
| 118 | b.y = box.min.y; |
---|
| 119 | else if (p.y > box.max.y) |
---|
| 120 | b.y = box.max.y; |
---|
| 121 | else |
---|
| 122 | b.y = p.y; |
---|
| 123 | |
---|
| 124 | if (p.z < box.min.z) |
---|
| 125 | b.z = box.min.z; |
---|
| 126 | else if (p.z > box.max.z) |
---|
| 127 | b.z = box.max.z; |
---|
| 128 | else |
---|
| 129 | b.z = p.z; |
---|
| 130 | |
---|
| 131 | return b; |
---|
| 132 | } |
---|
| 133 | |
---|
| 134 | template <class T> |
---|
| 135 | Vec3<T> closestPointOnBox(const Vec3<T>& pt, const Box< Vec3<T> >& box ) |
---|
| 136 | { |
---|
| 137 | // |
---|
| 138 | // This sucker is specialized to work with a Vec3f and a box |
---|
| 139 | // made of Vec3fs. |
---|
| 140 | // |
---|
| 141 | |
---|
| 142 | Vec3<T> result; |
---|
| 143 | |
---|
| 144 | // trivial cases first |
---|
| 145 | if (box.isEmpty()) |
---|
| 146 | return pt; |
---|
| 147 | else if (pt == box.center()) |
---|
| 148 | { |
---|
| 149 | // middle of z side |
---|
| 150 | result[0] = (box.max[0] + box.min[0])/2.0; |
---|
| 151 | result[1] = (box.max[1] + box.min[1])/2.0; |
---|
| 152 | result[2] = box.max[2]; |
---|
| 153 | } |
---|
| 154 | else |
---|
| 155 | { |
---|
| 156 | // Find the closest point on a unit box (from -1 to 1), |
---|
| 157 | // then scale up. |
---|
| 158 | |
---|
| 159 | // Find the vector from center to the point, then scale |
---|
| 160 | // to a unit box. |
---|
| 161 | Vec3<T> vec = pt - box.center(); |
---|
| 162 | T sizeX = box.max[0]-box.min[0]; |
---|
| 163 | T sizeY = box.max[1]-box.min[1]; |
---|
| 164 | T sizeZ = box.max[2]-box.min[2]; |
---|
| 165 | |
---|
| 166 | T halfX = sizeX/2.0; |
---|
| 167 | T halfY = sizeY/2.0; |
---|
| 168 | T halfZ = sizeZ/2.0; |
---|
| 169 | if (halfX > 0.0) |
---|
| 170 | vec[0] /= halfX; |
---|
| 171 | if (halfY > 0.0) |
---|
| 172 | vec[1] /= halfY; |
---|
| 173 | if (halfZ > 0.0) |
---|
| 174 | vec[2] /= halfZ; |
---|
| 175 | |
---|
| 176 | // Side to snap side that has greatest magnitude in the vector. |
---|
| 177 | Vec3<T> mag; |
---|
| 178 | mag[0] = fabs(vec[0]); |
---|
| 179 | mag[1] = fabs(vec[1]); |
---|
| 180 | mag[2] = fabs(vec[2]); |
---|
| 181 | |
---|
| 182 | result = mag; |
---|
| 183 | |
---|
| 184 | // Check if beyond corners |
---|
| 185 | if (result[0] > 1.0) |
---|
| 186 | result[0] = 1.0; |
---|
| 187 | if (result[1] > 1.0) |
---|
| 188 | result[1] = 1.0; |
---|
| 189 | if (result[2] > 1.0) |
---|
| 190 | result[2] = 1.0; |
---|
| 191 | |
---|
| 192 | // snap to appropriate side |
---|
| 193 | if ((mag[0] > mag[1]) && (mag[0] > mag[2])) |
---|
| 194 | { |
---|
| 195 | result[0] = 1.0; |
---|
| 196 | } |
---|
| 197 | else if ((mag[1] > mag[0]) && (mag[1] > mag[2])) |
---|
| 198 | { |
---|
| 199 | result[1] = 1.0; |
---|
| 200 | } |
---|
| 201 | else if ((mag[2] > mag[0]) && (mag[2] > mag[1])) |
---|
| 202 | { |
---|
| 203 | result[2] = 1.0; |
---|
| 204 | } |
---|
| 205 | else if ((mag[0] == mag[1]) && (mag[0] == mag[2])) |
---|
| 206 | { |
---|
| 207 | // corner |
---|
| 208 | result = Vec3<T>(1,1,1); |
---|
| 209 | } |
---|
| 210 | else if (mag[0] == mag[1]) |
---|
| 211 | { |
---|
| 212 | // edge parallel with z |
---|
| 213 | result[0] = 1.0; |
---|
| 214 | result[1] = 1.0; |
---|
| 215 | } |
---|
| 216 | else if (mag[0] == mag[2]) |
---|
| 217 | { |
---|
| 218 | // edge parallel with y |
---|
| 219 | result[0] = 1.0; |
---|
| 220 | result[2] = 1.0; |
---|
| 221 | } |
---|
| 222 | else if (mag[1] == mag[2]) |
---|
| 223 | { |
---|
| 224 | // edge parallel with x |
---|
| 225 | result[1] = 1.0; |
---|
| 226 | result[2] = 1.0; |
---|
| 227 | } |
---|
| 228 | |
---|
| 229 | // Now make everything point the right way |
---|
| 230 | for (int i=0; i < 3; i++) |
---|
| 231 | { |
---|
| 232 | if (vec[i] < 0.0) |
---|
| 233 | result[i] = -result[i]; |
---|
| 234 | } |
---|
| 235 | |
---|
| 236 | // scale back up and move to center |
---|
| 237 | result[0] *= halfX; |
---|
| 238 | result[1] *= halfY; |
---|
| 239 | result[2] *= halfZ; |
---|
| 240 | |
---|
| 241 | result += box.center(); |
---|
| 242 | } |
---|
| 243 | return result; |
---|
| 244 | } |
---|
| 245 | |
---|
| 246 | template <class S, class T> |
---|
| 247 | Box< Vec3<S> > |
---|
| 248 | transform(const Box< Vec3<S> >& box, const Matrix44<T>& m) |
---|
| 249 | { |
---|
| 250 | // Transforms Box3f by matrix, enlarging Box3f to contain result. |
---|
| 251 | // Clever method courtesy of Graphics Gems, pp. 548-550 |
---|
| 252 | // |
---|
| 253 | // This works for projection matrices as well as simple affine |
---|
| 254 | // transformations. Coordinates of the box are rehomogenized if there |
---|
| 255 | // is a projection matrix |
---|
| 256 | |
---|
| 257 | // a transformed empty box is still empty |
---|
| 258 | if (box.isEmpty()) |
---|
| 259 | return box; |
---|
| 260 | |
---|
| 261 | // If the last column is close enuf to ( 0 0 0 1 ) then we use the |
---|
| 262 | // fast, affine version. The tricky affine method could maybe be |
---|
| 263 | // extended to deal with the projection case as well, but its not |
---|
| 264 | // worth it right now. |
---|
| 265 | |
---|
| 266 | if (m[0][3] * m[0][3] + m[1][3] * m[1][3] + m[2][3] * m[2][3] |
---|
| 267 | + (1.0 - m[3][3]) * (1.0 - m[3][3]) < 0.00001) |
---|
| 268 | { |
---|
| 269 | // Affine version, use the Graphics Gems hack |
---|
| 270 | int i, j; |
---|
| 271 | Box< Vec3<S> > newBox; |
---|
| 272 | |
---|
| 273 | for (i = 0; i < 3; i++) |
---|
| 274 | { |
---|
| 275 | newBox.min[i] = newBox.max[i] = (S) m[3][i]; |
---|
| 276 | |
---|
| 277 | for (j = 0; j < 3; j++) |
---|
| 278 | { |
---|
| 279 | float a, b; |
---|
| 280 | |
---|
| 281 | a = (S) m[j][i] * box.min[j]; |
---|
| 282 | b = (S) m[j][i] * box.max[j]; |
---|
| 283 | |
---|
| 284 | if (a < b) |
---|
| 285 | { |
---|
| 286 | newBox.min[i] += a; |
---|
| 287 | newBox.max[i] += b; |
---|
| 288 | } |
---|
| 289 | else |
---|
| 290 | { |
---|
| 291 | newBox.min[i] += b; |
---|
| 292 | newBox.max[i] += a; |
---|
| 293 | } |
---|
| 294 | } |
---|
| 295 | } |
---|
| 296 | |
---|
| 297 | return newBox; |
---|
| 298 | } |
---|
| 299 | |
---|
| 300 | // This is a projection matrix. Do things the naive way. |
---|
| 301 | Vec3<S> points[8]; |
---|
| 302 | |
---|
| 303 | /* Set up the eight points at the corners of the extent */ |
---|
| 304 | points[0][0] = points[1][0] = points[2][0] = points[3][0] = box.min[0]; |
---|
| 305 | points[4][0] = points[5][0] = points[6][0] = points[7][0] = box.max[0]; |
---|
| 306 | |
---|
| 307 | points[0][1] = points[1][1] = points[4][1] = points[5][1] = box.min[1]; |
---|
| 308 | points[2][1] = points[3][1] = points[6][1] = points[7][1] = box.max[1]; |
---|
| 309 | |
---|
| 310 | points[0][2] = points[2][2] = points[4][2] = points[6][2] = box.min[2]; |
---|
| 311 | points[1][2] = points[3][2] = points[5][2] = points[7][2] = box.max[2]; |
---|
| 312 | |
---|
| 313 | Box< Vec3<S> > newBox; |
---|
| 314 | for (int i = 0; i < 8; i++) |
---|
| 315 | newBox.extendBy(points[i] * m); |
---|
| 316 | |
---|
| 317 | return newBox; |
---|
| 318 | } |
---|
| 319 | |
---|
| 320 | template <class T> |
---|
| 321 | Box< Vec3<T> > |
---|
| 322 | affineTransform(const Box< Vec3<T> > &bbox, const Matrix44<T> &M) |
---|
| 323 | { |
---|
| 324 | float min0, max0, min1, max1, min2, max2, a, b; |
---|
| 325 | float min0new, max0new, min1new, max1new, min2new, max2new; |
---|
| 326 | |
---|
| 327 | min0 = bbox.min[0]; |
---|
| 328 | max0 = bbox.max[0]; |
---|
| 329 | min1 = bbox.min[1]; |
---|
| 330 | max1 = bbox.max[1]; |
---|
| 331 | min2 = bbox.min[2]; |
---|
| 332 | max2 = bbox.max[2]; |
---|
| 333 | |
---|
| 334 | min0new = max0new = M[3][0]; |
---|
| 335 | a = M[0][0] * min0; |
---|
| 336 | b = M[0][0] * max0; |
---|
| 337 | if (a < b) { |
---|
| 338 | min0new += a; |
---|
| 339 | max0new += b; |
---|
| 340 | } else { |
---|
| 341 | min0new += b; |
---|
| 342 | max0new += a; |
---|
| 343 | } |
---|
| 344 | a = M[1][0] * min1; |
---|
| 345 | b = M[1][0] * max1; |
---|
| 346 | if (a < b) { |
---|
| 347 | min0new += a; |
---|
| 348 | max0new += b; |
---|
| 349 | } else { |
---|
| 350 | min0new += b; |
---|
| 351 | max0new += a; |
---|
| 352 | } |
---|
| 353 | a = M[2][0] * min2; |
---|
| 354 | b = M[2][0] * max2; |
---|
| 355 | if (a < b) { |
---|
| 356 | min0new += a; |
---|
| 357 | max0new += b; |
---|
| 358 | } else { |
---|
| 359 | min0new += b; |
---|
| 360 | max0new += a; |
---|
| 361 | } |
---|
| 362 | |
---|
| 363 | min1new = max1new = M[3][1]; |
---|
| 364 | a = M[0][1] * min0; |
---|
| 365 | b = M[0][1] * max0; |
---|
| 366 | if (a < b) { |
---|
| 367 | min1new += a; |
---|
| 368 | max1new += b; |
---|
| 369 | } else { |
---|
| 370 | min1new += b; |
---|
| 371 | max1new += a; |
---|
| 372 | } |
---|
| 373 | a = M[1][1] * min1; |
---|
| 374 | b = M[1][1] * max1; |
---|
| 375 | if (a < b) { |
---|
| 376 | min1new += a; |
---|
| 377 | max1new += b; |
---|
| 378 | } else { |
---|
| 379 | min1new += b; |
---|
| 380 | max1new += a; |
---|
| 381 | } |
---|
| 382 | a = M[2][1] * min2; |
---|
| 383 | b = M[2][1] * max2; |
---|
| 384 | if (a < b) { |
---|
| 385 | min1new += a; |
---|
| 386 | max1new += b; |
---|
| 387 | } else { |
---|
| 388 | min1new += b; |
---|
| 389 | max1new += a; |
---|
| 390 | } |
---|
| 391 | |
---|
| 392 | min2new = max2new = M[3][2]; |
---|
| 393 | a = M[0][2] * min0; |
---|
| 394 | b = M[0][2] * max0; |
---|
| 395 | if (a < b) { |
---|
| 396 | min2new += a; |
---|
| 397 | max2new += b; |
---|
| 398 | } else { |
---|
| 399 | min2new += b; |
---|
| 400 | max2new += a; |
---|
| 401 | } |
---|
| 402 | a = M[1][2] * min1; |
---|
| 403 | b = M[1][2] * max1; |
---|
| 404 | if (a < b) { |
---|
| 405 | min2new += a; |
---|
| 406 | max2new += b; |
---|
| 407 | } else { |
---|
| 408 | min2new += b; |
---|
| 409 | max2new += a; |
---|
| 410 | } |
---|
| 411 | a = M[2][2] * min2; |
---|
| 412 | b = M[2][2] * max2; |
---|
| 413 | if (a < b) { |
---|
| 414 | min2new += a; |
---|
| 415 | max2new += b; |
---|
| 416 | } else { |
---|
| 417 | min2new += b; |
---|
| 418 | max2new += a; |
---|
| 419 | } |
---|
| 420 | |
---|
| 421 | Box< Vec3<T> > xbbox; |
---|
| 422 | |
---|
| 423 | xbbox.min[0] = min0new; |
---|
| 424 | xbbox.max[0] = max0new; |
---|
| 425 | xbbox.min[1] = min1new; |
---|
| 426 | xbbox.max[1] = max1new; |
---|
| 427 | xbbox.min[2] = min2new; |
---|
| 428 | xbbox.max[2] = max2new; |
---|
| 429 | |
---|
| 430 | return xbbox; |
---|
| 431 | } |
---|
| 432 | |
---|
| 433 | |
---|
| 434 | template <class T> |
---|
| 435 | bool findEntryAndExitPoints(const Line3<T>& line, |
---|
| 436 | const Box<Vec3<T> >& box, |
---|
| 437 | Vec3<T> &enterPoint, |
---|
| 438 | Vec3<T> &exitPoint) |
---|
| 439 | { |
---|
| 440 | if ( box.isEmpty() ) return false; |
---|
| 441 | if ( line.distanceTo(box.center()) > box.size().length()/2. ) return false; |
---|
| 442 | |
---|
| 443 | Vec3<T> points[8], inter, bary; |
---|
| 444 | Plane3<T> plane; |
---|
| 445 | int i, v0, v1, v2; |
---|
| 446 | bool front = false, valid, validIntersection = false; |
---|
| 447 | |
---|
| 448 | // set up the eight coords of the corners of the box |
---|
| 449 | for(i = 0; i < 8; i++) |
---|
| 450 | { |
---|
| 451 | points[i].setValue( i & 01 ? box.min[0] : box.max[0], |
---|
| 452 | i & 02 ? box.min[1] : box.max[1], |
---|
| 453 | i & 04 ? box.min[2] : box.max[2]); |
---|
| 454 | } |
---|
| 455 | |
---|
| 456 | // intersect the 12 triangles. |
---|
| 457 | for(i = 0; i < 12; i++) |
---|
| 458 | { |
---|
| 459 | switch(i) |
---|
| 460 | { |
---|
| 461 | case 0: v0 = 2; v1 = 1; v2 = 0; break; // +z |
---|
| 462 | case 1: v0 = 2; v1 = 3; v2 = 1; break; |
---|
| 463 | |
---|
| 464 | case 2: v0 = 4; v1 = 5; v2 = 6; break; // -z |
---|
| 465 | case 3: v0 = 6; v1 = 5; v2 = 7; break; |
---|
| 466 | |
---|
| 467 | case 4: v0 = 0; v1 = 6; v2 = 2; break; // -x |
---|
| 468 | case 5: v0 = 0; v1 = 4; v2 = 6; break; |
---|
| 469 | |
---|
| 470 | case 6: v0 = 1; v1 = 3; v2 = 7; break; // +x |
---|
| 471 | case 7: v0 = 1; v1 = 7; v2 = 5; break; |
---|
| 472 | |
---|
| 473 | case 8: v0 = 1; v1 = 4; v2 = 0; break; // -y |
---|
| 474 | case 9: v0 = 1; v1 = 5; v2 = 4; break; |
---|
| 475 | |
---|
| 476 | case 10: v0 = 2; v1 = 7; v2 = 3; break; // +y |
---|
| 477 | case 11: v0 = 2; v1 = 6; v2 = 7; break; |
---|
| 478 | } |
---|
| 479 | if((valid=intersect (line, points[v0], points[v1], points[v2], |
---|
| 480 | inter, bary, front)) == true) |
---|
| 481 | { |
---|
| 482 | if(front == true) |
---|
| 483 | { |
---|
| 484 | enterPoint = inter; |
---|
| 485 | validIntersection = valid; |
---|
| 486 | } |
---|
| 487 | else |
---|
| 488 | { |
---|
| 489 | exitPoint = inter; |
---|
| 490 | validIntersection = valid; |
---|
| 491 | } |
---|
| 492 | } |
---|
| 493 | } |
---|
| 494 | return validIntersection; |
---|
| 495 | } |
---|
| 496 | |
---|
| 497 | template<class T> |
---|
| 498 | bool intersects(const Box< Vec3<T> > &box, |
---|
| 499 | const Line3<T> &line, |
---|
| 500 | Vec3<T> &result) |
---|
| 501 | { |
---|
| 502 | /* |
---|
| 503 | Fast Ray-Box Intersection |
---|
| 504 | by Andrew Woo |
---|
| 505 | from "Graphics Gems", Academic Press, 1990 |
---|
| 506 | */ |
---|
| 507 | |
---|
| 508 | const int right = 0; |
---|
| 509 | const int left = 1; |
---|
| 510 | const int middle = 2; |
---|
| 511 | |
---|
| 512 | const Vec3<T> &minB = box.min; |
---|
| 513 | const Vec3<T> &maxB = box.max; |
---|
| 514 | const Vec3<T> &origin = line.pos; |
---|
| 515 | const Vec3<T> &dir = line.dir; |
---|
| 516 | |
---|
| 517 | bool inside = true; |
---|
| 518 | char quadrant[3]; |
---|
| 519 | int whichPlane; |
---|
| 520 | float maxT[3]; |
---|
| 521 | float candidatePlane[3]; |
---|
| 522 | |
---|
| 523 | /* Find candidate planes; this loop can be avoided if |
---|
| 524 | rays cast all from the eye(assume perpsective view) */ |
---|
| 525 | for (int i=0; i<3; i++) |
---|
| 526 | { |
---|
| 527 | if(origin[i] < minB[i]) |
---|
| 528 | { |
---|
| 529 | quadrant[i] = left; |
---|
| 530 | candidatePlane[i] = minB[i]; |
---|
| 531 | inside = false; |
---|
| 532 | } |
---|
| 533 | else if (origin[i] > maxB[i]) |
---|
| 534 | { |
---|
| 535 | quadrant[i] = right; |
---|
| 536 | candidatePlane[i] = maxB[i]; |
---|
| 537 | inside = false; |
---|
| 538 | } |
---|
| 539 | else |
---|
| 540 | { |
---|
| 541 | quadrant[i] = middle; |
---|
| 542 | } |
---|
| 543 | } |
---|
| 544 | |
---|
| 545 | /* Ray origin inside bounding box */ |
---|
| 546 | if ( inside ) |
---|
| 547 | { |
---|
| 548 | result = origin; |
---|
| 549 | return true; |
---|
| 550 | } |
---|
| 551 | |
---|
| 552 | |
---|
| 553 | /* Calculate T distances to candidate planes */ |
---|
| 554 | for (int i = 0; i < 3; i++) |
---|
| 555 | { |
---|
| 556 | if (quadrant[i] != middle && dir[i] !=0.) |
---|
| 557 | { |
---|
| 558 | maxT[i] = (candidatePlane[i]-origin[i]) / dir[i]; |
---|
| 559 | } |
---|
| 560 | else |
---|
| 561 | { |
---|
| 562 | maxT[i] = -1.; |
---|
| 563 | } |
---|
| 564 | } |
---|
| 565 | |
---|
| 566 | /* Get largest of the maxT's for final choice of intersection */ |
---|
| 567 | whichPlane = 0; |
---|
| 568 | |
---|
| 569 | for (int i = 1; i < 3; i++) |
---|
| 570 | { |
---|
| 571 | if (maxT[whichPlane] < maxT[i]) |
---|
| 572 | { |
---|
| 573 | whichPlane = i; |
---|
| 574 | } |
---|
| 575 | } |
---|
| 576 | |
---|
| 577 | /* Check final candidate actually inside box */ |
---|
| 578 | if (maxT[whichPlane] < 0.) return false; |
---|
| 579 | |
---|
| 580 | for (int i = 0; i < 3; i++) |
---|
| 581 | { |
---|
| 582 | if (whichPlane != i) |
---|
| 583 | { |
---|
| 584 | result[i] = origin[i] + maxT[whichPlane] *dir[i]; |
---|
| 585 | |
---|
| 586 | if ((quadrant[i] == right && result[i] < minB[i]) || |
---|
| 587 | (quadrant[i] == left && result[i] > maxB[i])) |
---|
| 588 | { |
---|
| 589 | return false; /* outside box */ |
---|
| 590 | } |
---|
| 591 | } |
---|
| 592 | else |
---|
| 593 | { |
---|
| 594 | result[i] = candidatePlane[i]; |
---|
| 595 | } |
---|
| 596 | } |
---|
| 597 | |
---|
| 598 | return true; |
---|
| 599 | } |
---|
| 600 | |
---|
| 601 | template<class T> |
---|
| 602 | bool intersects(const Box< Vec3<T> > &box, const Line3<T> &line) |
---|
| 603 | { |
---|
| 604 | Vec3<T> ignored; |
---|
| 605 | return intersects(box,line,ignored); |
---|
| 606 | } |
---|
| 607 | |
---|
| 608 | |
---|
| 609 | } // namespace Imath |
---|
| 610 | |
---|
| 611 | #endif |
---|