Box.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // This code is in the public domain -- [email protected]
  2. #include "Box.h"
  3. #include "Box.inl"
  4. #include "Sphere.h"
  5. using namespace nv;
  6. // Clip the given segment against this box.
  7. bool Box::clipSegment(const Vector3 & origin, const Vector3 & dir, float * t_near, float * t_far) const {
  8. // Avoid aliasing.
  9. float tnear = *t_near;
  10. float tfar = *t_far;
  11. // clip ray segment to box
  12. for (int i = 0; i < 3; i++)
  13. {
  14. const float pos = origin.component[i] + tfar * dir.component[i];
  15. const float dt = tfar - tnear;
  16. if (dir.component[i] < 0) {
  17. // clip end point
  18. if (pos < minCorner.component[i]) {
  19. tfar = tnear + dt * (origin.component[i] - minCorner.component[i]) / (origin.component[i] - pos);
  20. }
  21. // clip start point
  22. if (origin.component[i] > maxCorner.component[i]) {
  23. tnear = tnear + dt * (origin.component[i] - maxCorner.component[i]) / (tfar * dir.component[i]);
  24. }
  25. }
  26. else {
  27. // clip end point
  28. if (pos > maxCorner.component[i]) {
  29. tfar = tnear + dt * (maxCorner.component[i] - origin.component[i]) / (pos - origin.component[i]);
  30. }
  31. // clip start point
  32. if (origin.component[i] < minCorner.component[i]) {
  33. tnear = tnear + dt * (minCorner.component[i] - origin.component[i]) / (tfar * dir.component[i]);
  34. }
  35. }
  36. if (tnear > tfar) {
  37. // Clipped away.
  38. return false;
  39. }
  40. }
  41. // Return result.
  42. *t_near = tnear;
  43. *t_far = tfar;
  44. return true;
  45. }
  46. float nv::distanceSquared(const Box &box, const Vector3 &point) {
  47. Vector3 closest;
  48. if (point.x < box.minCorner.x) closest.x = box.minCorner.x;
  49. else if (point.x > box.maxCorner.x) closest.x = box.maxCorner.x;
  50. else closest.x = point.x;
  51. if (point.y < box.minCorner.y) closest.y = box.minCorner.y;
  52. else if (point.y > box.maxCorner.y) closest.y = box.maxCorner.y;
  53. else closest.y = point.y;
  54. if (point.z < box.minCorner.z) closest.z = box.minCorner.z;
  55. else if (point.z > box.maxCorner.z) closest.z = box.maxCorner.z;
  56. else closest.z = point.z;
  57. return lengthSquared(point - closest);
  58. }
  59. bool nv::overlap(const Box &box, const Sphere &sphere) {
  60. return distanceSquared(box, sphere.center) < sphere.radius * sphere.radius;
  61. }
  62. bool nv::intersect(const Box & box, const Vector3 & p, const Vector3 & id, float * t /*= NULL*/) {
  63. // Precompute these in ray structure?
  64. int sdx = (id.x < 0);
  65. int sdy = (id.y < 0);
  66. int sdz = (id.z < 0);
  67. float tmin = (box.corner( sdx).x - p.x) * id.x;
  68. float tmax = (box.corner(1-sdx).x - p.x) * id.x;
  69. float tymin = (box.corner( sdy).y - p.y) * id.y;
  70. float tymax = (box.corner(1-sdy).y - p.y) * id.y;
  71. if ((tmin > tymax) || (tymin > tmax))
  72. return false;
  73. if (tymin > tmin) tmin = tymin;
  74. if (tymax < tmax) tmax = tymax;
  75. float tzmin = (box.corner( sdz).z - p.z) * id.z;
  76. float tzmax = (box.corner(1-sdz).z - p.z) * id.z;
  77. if ((tmin > tzmax) || (tzmin > tmax))
  78. return false;
  79. if (tzmin > tmin) tmin = tzmin;
  80. if (tzmax < tmax) tmax = tzmax;
  81. if (tmax < 0)
  82. return false;
  83. if (t != NULL) *t = tmin;
  84. return true;
  85. }