lbbox.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #include "bbox.h"
  5. #include "range.h"
  6. namespace embree
  7. {
  8. template<typename T>
  9. __forceinline std::pair<T,T> globalLinear(const std::pair<T,T>& v, const BBox1f& dt)
  10. {
  11. const float rcp_dt_size = float(1.0f)/dt.size();
  12. const T g0 = lerp(v.first,v.second,-dt.lower*rcp_dt_size);
  13. const T g1 = lerp(v.first,v.second,(1.0f-dt.lower)*rcp_dt_size);
  14. return std::make_pair(g0,g1);
  15. }
  16. template<typename T>
  17. struct LBBox
  18. {
  19. public:
  20. __forceinline LBBox () {}
  21. template<typename T1>
  22. __forceinline LBBox ( const LBBox<T1>& other )
  23. : bounds0(other.bounds0), bounds1(other.bounds1) {}
  24. __forceinline LBBox& operator= ( const LBBox& other ) {
  25. bounds0 = other.bounds0; bounds1 = other.bounds1; return *this;
  26. }
  27. __forceinline LBBox (EmptyTy)
  28. : bounds0(EmptyTy()), bounds1(EmptyTy()) {}
  29. __forceinline explicit LBBox ( const BBox<T>& bounds)
  30. : bounds0(bounds), bounds1(bounds) { }
  31. __forceinline LBBox ( const BBox<T>& bounds0, const BBox<T>& bounds1)
  32. : bounds0(bounds0), bounds1(bounds1) { }
  33. LBBox ( const avector<BBox<T>>& bounds )
  34. {
  35. assert(bounds.size());
  36. BBox<T> b0 = bounds.front();
  37. BBox<T> b1 = bounds.back();
  38. for (size_t i=1; i<bounds.size()-1; i++) {
  39. const float f = float(i)/float(bounds.size()-1);
  40. const BBox<T> bt = lerp(b0,b1,f);
  41. const T dlower = min(bounds[i].lower-bt.lower,T(zero));
  42. const T dupper = max(bounds[i].upper-bt.upper,T(zero));
  43. b0.lower += dlower; b1.lower += dlower;
  44. b0.upper += dupper; b1.upper += dupper;
  45. }
  46. bounds0 = b0;
  47. bounds1 = b1;
  48. }
  49. /*! calculates the linear bounds of a primitive for the specified time range */
  50. template<typename BoundsFunc>
  51. __forceinline LBBox(const BoundsFunc& bounds, const BBox1f& time_range, float numTimeSegments)
  52. {
  53. const float lower = time_range.lower*numTimeSegments;
  54. const float upper = time_range.upper*numTimeSegments;
  55. const float ilowerf = floor(lower);
  56. const float iupperf = ceil(upper);
  57. const int ilower = (int)ilowerf;
  58. const int iupper = (int)iupperf;
  59. const BBox<T> blower0 = bounds(ilower);
  60. const BBox<T> bupper1 = bounds(iupper);
  61. if (iupper-ilower == 1) {
  62. bounds0 = lerp(blower0, bupper1, lower-ilowerf);
  63. bounds1 = lerp(bupper1, blower0, iupperf-upper);
  64. return;
  65. }
  66. const BBox<T> blower1 = bounds(ilower+1);
  67. const BBox<T> bupper0 = bounds(iupper-1);
  68. BBox<T> b0 = lerp(blower0, blower1, lower-ilowerf);
  69. BBox<T> b1 = lerp(bupper1, bupper0, iupperf-upper);
  70. for (int i = ilower+1; i < iupper; i++)
  71. {
  72. const float f = (float(i)/numTimeSegments - time_range.lower) / time_range.size();
  73. const BBox<T> bt = lerp(b0, b1, f);
  74. const BBox<T> bi = bounds(i);
  75. const T dlower = min(bi.lower-bt.lower, T(zero));
  76. const T dupper = max(bi.upper-bt.upper, T(zero));
  77. b0.lower += dlower; b1.lower += dlower;
  78. b0.upper += dupper; b1.upper += dupper;
  79. }
  80. bounds0 = b0;
  81. bounds1 = b1;
  82. }
  83. /*! calculates the linear bounds of a primitive for the specified time range */
  84. template<typename BoundsFunc>
  85. __forceinline LBBox(const BoundsFunc& bounds, const BBox1f& time_range_in, const BBox1f& geom_time_range, float geom_time_segments)
  86. {
  87. /* normalize global time_range_in to local geom_time_range */
  88. const BBox1f time_range((time_range_in.lower-geom_time_range.lower)/geom_time_range.size(),
  89. (time_range_in.upper-geom_time_range.lower)/geom_time_range.size());
  90. const float lower = time_range.lower*geom_time_segments;
  91. const float upper = time_range.upper*geom_time_segments;
  92. const float ilowerf = floor(lower);
  93. const float iupperf = ceil(upper);
  94. const float ilowerfc = max(0.0f,ilowerf);
  95. const float iupperfc = min(iupperf,geom_time_segments);
  96. const int ilowerc = (int)ilowerfc;
  97. const int iupperc = (int)iupperfc;
  98. assert(iupperc-ilowerc > 0);
  99. /* this larger iteration range guarantees that we process borders of geom_time_range is (partially) inside time_range_in */
  100. const int ilower_iter = max(-1,(int)ilowerf);
  101. const int iupper_iter = min((int)iupperf,(int)geom_time_segments+1);
  102. const BBox<T> blower0 = bounds(ilowerc);
  103. const BBox<T> bupper1 = bounds(iupperc);
  104. if (iupper_iter-ilower_iter == 1) {
  105. bounds0 = lerp(blower0, bupper1, max(0.0f,lower-ilowerfc));
  106. bounds1 = lerp(bupper1, blower0, max(0.0f,iupperfc-upper));
  107. return;
  108. }
  109. const BBox<T> blower1 = bounds(ilowerc+1);
  110. const BBox<T> bupper0 = bounds(iupperc-1);
  111. BBox<T> b0 = lerp(blower0, blower1, max(0.0f,lower-ilowerfc));
  112. BBox<T> b1 = lerp(bupper1, bupper0, max(0.0f,iupperfc-upper));
  113. for (int i = ilower_iter+1; i < iupper_iter; i++)
  114. {
  115. const float f = (float(i)/geom_time_segments - time_range.lower) / time_range.size();
  116. const BBox<T> bt = lerp(b0, b1, f);
  117. const BBox<T> bi = bounds(i);
  118. const T dlower = min(bi.lower-bt.lower, T(zero));
  119. const T dupper = max(bi.upper-bt.upper, T(zero));
  120. b0.lower += dlower; b1.lower += dlower;
  121. b0.upper += dupper; b1.upper += dupper;
  122. }
  123. bounds0 = b0;
  124. bounds1 = b1;
  125. }
  126. /*! calculates the linear bounds of a primitive for the specified time range */
  127. template<typename BoundsFunc>
  128. __forceinline LBBox(const BoundsFunc& bounds, const range<int>& time_range, int numTimeSegments)
  129. {
  130. const int ilower = time_range.begin();
  131. const int iupper = time_range.end();
  132. BBox<T> b0 = bounds(ilower);
  133. BBox<T> b1 = bounds(iupper);
  134. if (iupper-ilower == 1)
  135. {
  136. bounds0 = b0;
  137. bounds1 = b1;
  138. return;
  139. }
  140. for (int i = ilower+1; i<iupper; i++)
  141. {
  142. const float f = float(i - time_range.begin()) / float(time_range.size());
  143. const BBox<T> bt = lerp(b0, b1, f);
  144. const BBox<T> bi = bounds(i);
  145. const T dlower = min(bi.lower-bt.lower, T(zero));
  146. const T dupper = max(bi.upper-bt.upper, T(zero));
  147. b0.lower += dlower; b1.lower += dlower;
  148. b0.upper += dupper; b1.upper += dupper;
  149. }
  150. bounds0 = b0;
  151. bounds1 = b1;
  152. }
  153. public:
  154. __forceinline bool empty() const {
  155. return bounds().empty();
  156. }
  157. __forceinline BBox<T> bounds () const {
  158. return merge(bounds0,bounds1);
  159. }
  160. __forceinline BBox<T> interpolate( const float t ) const {
  161. return lerp(bounds0,bounds1,t);
  162. }
  163. __forceinline LBBox<T> interpolate( const BBox1f& dt ) const {
  164. return LBBox<T>(interpolate(dt.lower),interpolate(dt.upper));
  165. }
  166. __forceinline void extend( const LBBox& other ) {
  167. bounds0.extend(other.bounds0);
  168. bounds1.extend(other.bounds1);
  169. }
  170. __forceinline float expectedHalfArea() const;
  171. __forceinline float expectedHalfArea(const BBox1f& dt) const {
  172. return interpolate(dt).expectedHalfArea();
  173. }
  174. __forceinline float expectedApproxHalfArea() const {
  175. return 0.5f*(halfArea(bounds0) + halfArea(bounds1));
  176. }
  177. /* calculates bounds for [0,1] time range from bounds in dt time range */
  178. __forceinline LBBox global(const BBox1f& dt) const
  179. {
  180. const float rcp_dt_size = 1.0f/dt.size();
  181. const BBox<T> b0 = interpolate(-dt.lower*rcp_dt_size);
  182. const BBox<T> b1 = interpolate((1.0f-dt.lower)*rcp_dt_size);
  183. return LBBox(b0,b1);
  184. }
  185. /*! Comparison Operators */
  186. //template<typename TT> friend __forceinline bool operator==( const LBBox<TT>& a, const LBBox<TT>& b ) { return a.bounds0 == b.bounds0 && a.bounds1 == b.bounds1; }
  187. //template<typename TT> friend __forceinline bool operator!=( const LBBox<TT>& a, const LBBox<TT>& b ) { return a.bounds0 != b.bounds0 || a.bounds1 != b.bounds1; }
  188. friend __forceinline bool operator==( const LBBox& a, const LBBox& b ) { return a.bounds0 == b.bounds0 && a.bounds1 == b.bounds1; }
  189. friend __forceinline bool operator!=( const LBBox& a, const LBBox& b ) { return a.bounds0 != b.bounds0 || a.bounds1 != b.bounds1; }
  190. /*! output operator */
  191. friend __forceinline embree_ostream operator<<(embree_ostream cout, const LBBox& box) {
  192. return cout << "LBBox { " << box.bounds0 << "; " << box.bounds1 << " }";
  193. }
  194. public:
  195. BBox<T> bounds0, bounds1;
  196. };
  197. /*! tests if box is finite */
  198. template<typename T>
  199. __forceinline bool isvalid( const LBBox<T>& v ) {
  200. return isvalid(v.bounds0) && isvalid(v.bounds1);
  201. }
  202. template<typename T>
  203. __forceinline bool isvalid_non_empty( const LBBox<T>& v ) {
  204. return isvalid_non_empty(v.bounds0) && isvalid_non_empty(v.bounds1);
  205. }
  206. template<typename T>
  207. __forceinline T expectedArea(const T& a0, const T& a1, const T& b0, const T& b1)
  208. {
  209. const T da = a1-a0;
  210. const T db = b1-b0;
  211. return a0*b0+(a0*db+da*b0)*T(0.5f) + da*db*T(1.0f/3.0f);
  212. }
  213. template<> __forceinline float LBBox<Vec3fa>::expectedHalfArea() const
  214. {
  215. const Vec3fa d0 = bounds0.size();
  216. const Vec3fa d1 = bounds1.size();
  217. return reduce_add(expectedArea(Vec3fa(d0.x,d0.y,d0.z),
  218. Vec3fa(d1.x,d1.y,d1.z),
  219. Vec3fa(d0.y,d0.z,d0.x),
  220. Vec3fa(d1.y,d1.z,d1.x)));
  221. }
  222. template<typename T>
  223. __forceinline float expectedApproxHalfArea(const LBBox<T>& box) {
  224. return box.expectedApproxHalfArea();
  225. }
  226. template<typename T>
  227. __forceinline LBBox<T> merge(const LBBox<T>& a, const LBBox<T>& b) {
  228. return LBBox<T>(merge(a.bounds0, b.bounds0), merge(a.bounds1, b.bounds1));
  229. }
  230. /*! subset relation */
  231. template<typename T> __inline bool subset( const LBBox<T>& a, const LBBox<T>& b ) {
  232. return subset(a.bounds0,b.bounds0) && subset(a.bounds1,b.bounds1);
  233. }
  234. /*! default template instantiations */
  235. typedef LBBox<float> LBBox1f;
  236. typedef LBBox<Vec2f> LBBox2f;
  237. typedef LBBox<Vec3f> LBBox3f;
  238. typedef LBBox<Vec3fa> LBBox3fa;
  239. typedef LBBox<Vec3fx> LBBox3fx;
  240. }