bbox.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. // ======================================================================== //
  2. // Copyright 2009-2017 Intel Corporation //
  3. // //
  4. // Licensed under the Apache License, Version 2.0 (the "License"); //
  5. // you may not use this file except in compliance with the License. //
  6. // You may obtain a copy of the License at //
  7. // //
  8. // http://www.apache.org/licenses/LICENSE-2.0 //
  9. // //
  10. // Unless required by applicable law or agreed to in writing, software //
  11. // distributed under the License is distributed on an "AS IS" BASIS, //
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
  13. // See the License for the specific language governing permissions and //
  14. // limitations under the License. //
  15. // ======================================================================== //
  16. #pragma once
  17. #include "vec2.h"
  18. #include "vec3.h"
  19. namespace embree
  20. {
  21. template<typename T>
  22. struct BBox
  23. {
  24. T lower, upper;
  25. ////////////////////////////////////////////////////////////////////////////////
  26. /// Construction
  27. ////////////////////////////////////////////////////////////////////////////////
  28. __forceinline BBox ( ) { }
  29. __forceinline BBox ( const BBox& other ) { lower = other.lower; upper = other.upper; }
  30. __forceinline BBox& operator=( const BBox& other ) { lower = other.lower; upper = other.upper; return *this; }
  31. __forceinline BBox ( const T& v ) : lower(v), upper(v) {}
  32. __forceinline BBox ( const T& lower, const T& upper ) : lower(lower), upper(upper) {}
  33. ////////////////////////////////////////////////////////////////////////////////
  34. /// Extending Bounds
  35. ////////////////////////////////////////////////////////////////////////////////
  36. __forceinline const BBox& extend(const BBox& other) { lower = min(lower,other.lower); upper = max(upper,other.upper); return *this; }
  37. __forceinline const BBox& extend(const T & other) { lower = min(lower,other ); upper = max(upper,other ); return *this; }
  38. /*! tests if box is empty */
  39. __forceinline bool empty() const { for (int i=0; i<T::N; i++) if (lower[i] > upper[i]) return true; return false; }
  40. /*! computes the size of the box */
  41. __forceinline T size() const { return upper - lower; }
  42. /*! computes the center of the box */
  43. __forceinline T center() const { return 0.5f*(lower+upper); }
  44. /*! computes twice the center of the box */
  45. __forceinline T center2() const { return lower+upper; }
  46. /*! merges two boxes */
  47. __forceinline static const BBox merge (const BBox& a, const BBox& b) {
  48. return BBox(min(a.lower, b.lower), max(a.upper, b.upper));
  49. }
  50. ////////////////////////////////////////////////////////////////////////////////
  51. /// Constants
  52. ////////////////////////////////////////////////////////////////////////////////
  53. __forceinline BBox( EmptyTy ) : lower(pos_inf), upper(neg_inf) {}
  54. __forceinline BBox( FullTy ) : lower(neg_inf), upper(pos_inf) {}
  55. __forceinline BBox( FalseTy ) : lower(pos_inf), upper(neg_inf) {}
  56. __forceinline BBox( TrueTy ) : lower(neg_inf), upper(pos_inf) {}
  57. __forceinline BBox( NegInfTy ): lower(pos_inf), upper(neg_inf) {}
  58. __forceinline BBox( PosInfTy ): lower(neg_inf), upper(pos_inf) {}
  59. };
  60. template<> __forceinline bool BBox<float>::empty() const {
  61. return lower > upper;
  62. }
  63. #if defined(__SSE__)
  64. template<> __forceinline bool BBox<Vec3fa>::empty() const {
  65. return !all(le_mask(lower,upper));
  66. }
  67. #endif
  68. /*! tests if box is finite */
  69. __forceinline bool isvalid( const BBox<Vec3fa>& v ) {
  70. return all(gt_mask(v.lower,Vec3fa_t(-FLT_LARGE)) & lt_mask(v.upper,Vec3fa_t(+FLT_LARGE)));
  71. }
  72. /*! tests if box has finite entries */
  73. __forceinline bool is_finite( const BBox<Vec3fa>& b) {
  74. return is_finite(b.lower) && is_finite(b.upper);
  75. }
  76. /*! test if point contained in box */
  77. __forceinline bool inside ( const BBox<Vec3fa>& b, const Vec3fa& p ) { return all(ge_mask(p,b.lower) & le_mask(p,b.upper)); }
  78. /*! computes the center of the box */
  79. template<typename T> __forceinline const T center2(const BBox<T>& box) { return box.lower + box.upper; }
  80. template<typename T> __forceinline const T center (const BBox<T>& box) { return T(0.5f)*center2(box); }
  81. /*! computes the volume of a bounding box */
  82. __forceinline float volume ( const BBox<Vec3fa>& b ) { return reduce_mul(b.size()); }
  83. __forceinline float safeVolume( const BBox<Vec3fa>& b ) { if (b.empty()) return 0.0f; else return volume(b); }
  84. /*! computes the volume of a bounding box */
  85. __forceinline float volume( const BBox<Vec3f>& b ) { return reduce_mul(b.size()); }
  86. /*! computes the surface area of a bounding box */
  87. template<typename T> __forceinline const T area( const BBox<Vec2<T> >& b ) { const Vec2<T> d = b.size(); return d.x*d.y; }
  88. template<typename T> __forceinline const T halfArea( const BBox<Vec3<T> >& b ) { return halfArea(b.size()); }
  89. template<typename T> __forceinline const T area( const BBox<Vec3<T> >& b ) { return 2.0f*halfArea(b); }
  90. __forceinline float halfArea( const BBox<Vec3fa>& b ) { return halfArea(b.size()); }
  91. __forceinline float area( const BBox<Vec3fa>& b ) { return 2.0f*halfArea(b); }
  92. template<typename Vec> __forceinline float safeArea( const BBox<Vec>& b ) { if (b.empty()) return 0.0f; else return area(b); }
  93. template<typename T> __forceinline float expectedApproxHalfArea(const BBox<T>& box) {
  94. return halfArea(box);
  95. }
  96. /*! merges bounding boxes and points */
  97. template<typename T> __forceinline const BBox<T> merge( const BBox<T>& a, const T& b ) { return BBox<T>(min(a.lower, b ), max(a.upper, b )); }
  98. template<typename T> __forceinline const BBox<T> merge( const T& a, const BBox<T>& b ) { return BBox<T>(min(a , b.lower), max(a , b.upper)); }
  99. template<typename T> __forceinline const BBox<T> merge( const BBox<T>& a, const BBox<T>& b ) { return BBox<T>(min(a.lower, b.lower), max(a.upper, b.upper)); }
  100. /*! Merges three boxes. */
  101. template<typename T> __forceinline const BBox<T> merge( const BBox<T>& a, const BBox<T>& b, const BBox<T>& c ) { return merge(a,merge(b,c)); }
  102. /*! Merges four boxes. */
  103. template<typename T> __forceinline BBox<T> merge(const BBox<T>& a, const BBox<T>& b, const BBox<T>& c, const BBox<T>& d) {
  104. return merge(merge(a,b),merge(c,d));
  105. }
  106. /*! Comparison Operators */
  107. template<typename T> __forceinline bool operator==( const BBox<T>& a, const BBox<T>& b ) { return a.lower == b.lower && a.upper == b.upper; }
  108. template<typename T> __forceinline bool operator!=( const BBox<T>& a, const BBox<T>& b ) { return a.lower != b.lower || a.upper != b.upper; }
  109. /*! scaling */
  110. template<typename T> __forceinline BBox<T> operator *( const float& a, const BBox<T>& b ) { return BBox<T>(a*b.lower,a*b.upper); }
  111. template<typename T> __forceinline BBox<T> operator *( const T& a, const BBox<T>& b ) { return BBox<T>(a*b.lower,a*b.upper); }
  112. /*! translations */
  113. template<typename T> __forceinline BBox<T> operator +( const BBox<T>& a, const BBox<T>& b ) { return BBox<T>(a.lower+b.lower,a.upper+b.upper); }
  114. template<typename T> __forceinline BBox<T> operator -( const BBox<T>& a, const BBox<T>& b ) { return BBox<T>(a.lower-b.lower,a.upper-b.upper); }
  115. template<typename T> __forceinline BBox<T> operator +( const BBox<T>& a, const T & b ) { return BBox<T>(a.lower+b ,a.upper+b ); }
  116. template<typename T> __forceinline BBox<T> operator -( const BBox<T>& a, const T & b ) { return BBox<T>(a.lower-b ,a.upper-b ); }
  117. /*! extension */
  118. template<typename T> __forceinline BBox<T> enlarge(const BBox<T>& a, const T& b) { return BBox<T>(a.lower-b, a.upper+b); }
  119. /*! intersect bounding boxes */
  120. template<typename T> __forceinline const BBox<T> intersect( const BBox<T>& a, const BBox<T>& b ) { return BBox<T>(max(a.lower, b.lower), min(a.upper, b.upper)); }
  121. template<typename T> __forceinline const BBox<T> intersect( const BBox<T>& a, const BBox<T>& b, const BBox<T>& c ) { return intersect(a,intersect(b,c)); }
  122. template<typename T> __forceinline const BBox<T> intersect( const BBox<T>& a, const BBox<T>& b, const BBox<T>& c, const BBox<T>& d ) { return intersect(intersect(a,b),intersect(c,d)); }
  123. /*! subtract bounds from each other */
  124. template<typename T> __forceinline void subtract(const BBox<T>& a, const BBox<T>& b, BBox<T>& c, BBox<T>& d)
  125. {
  126. c.lower = a.lower;
  127. c.upper = min(a.upper,b.lower);
  128. d.lower = max(a.lower,b.upper);
  129. d.upper = a.upper;
  130. }
  131. /*! tests if bounding boxes (and points) are disjoint (empty intersection) */
  132. template<typename T> __inline bool disjoint( const BBox<T>& a, const BBox<T>& b ) { return intersect(a,b).empty(); }
  133. template<typename T> __inline bool disjoint( const BBox<T>& a, const T& b ) { return disjoint(a,BBox<T>(b)); }
  134. template<typename T> __inline bool disjoint( const T& a, const BBox<T>& b ) { return disjoint(BBox<T>(a),b); }
  135. /*! tests if bounding boxes (and points) are conjoint (non-empty intersection) */
  136. template<typename T> __inline bool conjoint( const BBox<T>& a, const BBox<T>& b ) { return !intersect(a,b).empty(); }
  137. template<typename T> __inline bool conjoint( const BBox<T>& a, const T& b ) { return conjoint(a,BBox<T>(b)); }
  138. template<typename T> __inline bool conjoint( const T& a, const BBox<T>& b ) { return conjoint(BBox<T>(a),b); }
  139. /*! subset relation */
  140. template<typename T> __inline bool subset( const BBox<T>& a, const BBox<T>& b )
  141. {
  142. for ( size_t i = 0; i < T::N; i++ ) if ( a.lower[i] < b.lower[i] ) return false;
  143. for ( size_t i = 0; i < T::N; i++ ) if ( a.upper[i] > b.upper[i] ) return false;
  144. return true;
  145. }
  146. /*! blending */
  147. template<typename T>
  148. __forceinline BBox<T> lerp(const BBox<T>& b0, const BBox<T>& b1, const float t) {
  149. return BBox<T>(lerp(b0.lower,b1.lower,t),lerp(b0.upper,b1.upper,t));
  150. }
  151. /*! output operator */
  152. template<typename T> __forceinline std::ostream& operator<<(std::ostream& cout, const BBox<T>& box) {
  153. return cout << "[" << box.lower << "; " << box.upper << "]";
  154. }
  155. /*! default template instantiations */
  156. typedef BBox<float> BBox1f;
  157. typedef BBox<Vec2f> BBox2f;
  158. typedef BBox<Vec3f> BBox3f;
  159. typedef BBox<Vec3fa> BBox3fa;
  160. }
  161. ////////////////////////////////////////////////////////////////////////////////
  162. /// SSE / AVX / MIC specializations
  163. ////////////////////////////////////////////////////////////////////////////////
  164. #if defined __SSE__
  165. #include "../simd/sse.h"
  166. #endif
  167. #if defined __AVX__
  168. #include "../simd/avx.h"
  169. #endif
  170. #if defined(__AVX512F__)
  171. #include "../simd/avx512.h"
  172. #endif
  173. namespace embree
  174. {
  175. template<int N>
  176. __forceinline BBox<Vec3<vfloat<N>>> transpose(const BBox3fa* bounds);
  177. template<>
  178. __forceinline BBox<Vec3<vfloat4>> transpose<4>(const BBox3fa* bounds)
  179. {
  180. BBox<Vec3<vfloat4>> dest;
  181. transpose((vfloat4&)bounds[0].lower,
  182. (vfloat4&)bounds[1].lower,
  183. (vfloat4&)bounds[2].lower,
  184. (vfloat4&)bounds[3].lower,
  185. dest.lower.x,
  186. dest.lower.y,
  187. dest.lower.z);
  188. transpose((vfloat4&)bounds[0].upper,
  189. (vfloat4&)bounds[1].upper,
  190. (vfloat4&)bounds[2].upper,
  191. (vfloat4&)bounds[3].upper,
  192. dest.upper.x,
  193. dest.upper.y,
  194. dest.upper.z);
  195. return dest;
  196. }
  197. #if defined(__AVX__)
  198. template<>
  199. __forceinline BBox<Vec3<vfloat8>> transpose<8>(const BBox3fa* bounds)
  200. {
  201. BBox<Vec3<vfloat8>> dest;
  202. transpose((vfloat4&)bounds[0].lower,
  203. (vfloat4&)bounds[1].lower,
  204. (vfloat4&)bounds[2].lower,
  205. (vfloat4&)bounds[3].lower,
  206. (vfloat4&)bounds[4].lower,
  207. (vfloat4&)bounds[5].lower,
  208. (vfloat4&)bounds[6].lower,
  209. (vfloat4&)bounds[7].lower,
  210. dest.lower.x,
  211. dest.lower.y,
  212. dest.lower.z);
  213. transpose((vfloat4&)bounds[0].upper,
  214. (vfloat4&)bounds[1].upper,
  215. (vfloat4&)bounds[2].upper,
  216. (vfloat4&)bounds[3].upper,
  217. (vfloat4&)bounds[4].upper,
  218. (vfloat4&)bounds[5].upper,
  219. (vfloat4&)bounds[6].upper,
  220. (vfloat4&)bounds[7].upper,
  221. dest.upper.x,
  222. dest.upper.y,
  223. dest.upper.z);
  224. return dest;
  225. }
  226. #endif
  227. template<int N>
  228. __forceinline BBox3fa merge(const BBox3fa* bounds);
  229. template<>
  230. __forceinline BBox3fa merge<4>(const BBox3fa* bounds)
  231. {
  232. const Vec3fa lower = min(min(bounds[0].lower,bounds[1].lower),
  233. min(bounds[2].lower,bounds[3].lower));
  234. const Vec3fa upper = max(max(bounds[0].upper,bounds[1].upper),
  235. max(bounds[2].upper,bounds[3].upper));
  236. return BBox3fa(lower,upper);
  237. }
  238. #if defined(__AVX__)
  239. template<>
  240. __forceinline BBox3fa merge<8>(const BBox3fa* bounds)
  241. {
  242. const Vec3fa lower = min(min(min(bounds[0].lower,bounds[1].lower),min(bounds[2].lower,bounds[3].lower)),
  243. min(min(bounds[4].lower,bounds[5].lower),min(bounds[6].lower,bounds[7].lower)));
  244. const Vec3fa upper = max(max(max(bounds[0].upper,bounds[1].upper),max(bounds[2].upper,bounds[3].upper)),
  245. max(max(bounds[4].upper,bounds[5].upper),max(bounds[6].upper,bounds[7].upper)));
  246. return BBox3fa(lower,upper);
  247. }
  248. #endif
  249. }