BoundingVolume.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. #include "BoundingVolume.h"
  2. namespace gameplay
  3. {
  4. BoundingVolume::BoundingVolume()
  5. : radius(0.0f)
  6. {
  7. }
  8. void updateMinMax(Vector3* point, Vector3* min, Vector3* max)
  9. {
  10. // Leftmost point.
  11. if (point->x < min->x)
  12. {
  13. min->x = point->x;
  14. }
  15. // Rightmost point.
  16. if (point->x > max->x)
  17. {
  18. max->x = point->x;
  19. }
  20. // Lowest point.
  21. if (point->y < min->y)
  22. {
  23. min->y = point->y;
  24. }
  25. // Highest point.
  26. if (point->y > max->y)
  27. {
  28. max->y = point->y;
  29. }
  30. // Farthest point.
  31. if (point->z < min->z)
  32. {
  33. min->z = point->z;
  34. }
  35. // Nearest point.
  36. if (point->z > max->z)
  37. {
  38. max->z = point->z;
  39. }
  40. }
  41. void BoundingVolume::transform(const Matrix& m)
  42. {
  43. // Transform the bounding sphere
  44. m.transformPoint(center, &center);
  45. Vector3 translate;
  46. m.decompose(&translate, NULL, NULL);
  47. float r = radius * translate.x;
  48. r = std::max(radius, radius * translate.y);
  49. r = std::max(radius, radius * translate.z);
  50. radius = r;
  51. // Transform the bounding box
  52. Vector3 corners[8];
  53. corners[0].set(min.x, max.y, max.z);
  54. // Left-bottom-front.
  55. corners[1].set(min.x, min.y, max.z);
  56. // Right-bottom-front.
  57. corners[2].set(max.x, min.y, max.z);
  58. // Right-top-front.
  59. corners[3].set(max.x, max.y, max.z);
  60. // Right-top-back.
  61. corners[4].set(max.x, max.y, min.z);
  62. // Right-bottom-back.
  63. corners[5].set(max.x, min.y, min.z);
  64. // Left-bottom-back.
  65. corners[6].set(min.x, min.y, min.z);
  66. // Left-top-back.
  67. corners[7].set(min.x, max.y, min.z);
  68. // Transform the corners, recalculating the min and max points along the way.
  69. m.transformPoint(corners[0], &corners[0]);
  70. Vector3 newMin = corners[0];
  71. Vector3 newMax = corners[0];
  72. for (int i = 1; i < 8; i++)
  73. {
  74. m.transformPoint(corners[i], &corners[i]);
  75. updateMinMax(&corners[i], &newMin, &newMax);
  76. }
  77. min = newMin;
  78. max = newMax;
  79. }
  80. void BoundingVolume::merge(const BoundingVolume& v)
  81. {
  82. // Calculate the distance between the two centers.
  83. float vx = center.x - v.center.x;
  84. float vy = center.y - v.center.y;
  85. float vz = center.z - v.center.z;
  86. float d = sqrtf(vx * vx + vy * vy + vz * vz);
  87. // If one sphere is contained inside the other, set to the larger sphere.
  88. if (d <= (v.radius - radius))
  89. {
  90. // Use targert volume
  91. radius = v.radius;
  92. center = v.center;
  93. }
  94. else if (d <= (radius - v.radius))
  95. {
  96. // No change
  97. }
  98. else
  99. {
  100. // Calculate the unit vector between the two centers.
  101. float dI = 1.0f / d;
  102. vx *= dI;
  103. vy *= dI;
  104. vz *= dI;
  105. // Calculate the new radius.
  106. float r = (radius + v.radius + d) * 0.5f;
  107. // Calculate the new center.
  108. float scaleFactor = (r - v.radius);
  109. vx = vx * scaleFactor + v.center.x;
  110. vy = vy * scaleFactor + v.center.y;
  111. vz = vz * scaleFactor + v.center.z;
  112. // Set the new center and radius.
  113. center.x = vx;
  114. center.y = vy;
  115. center.z = vz;
  116. radius = r;
  117. }
  118. }
  119. }