geometry.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  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 "default.h"
  18. namespace embree
  19. {
  20. class Scene;
  21. /*! Base class all geometries are derived from */
  22. class Geometry
  23. {
  24. friend class Scene;
  25. public:
  26. /*! type of geometry */
  27. enum Type { TRIANGLE_MESH = 1, USER_GEOMETRY = 2, BEZIER_CURVES = 4, SUBDIV_MESH = 8, INSTANCE = 16, QUAD_MESH = 32, LINE_SEGMENTS = 64 };
  28. public:
  29. /*! Geometry constructor */
  30. Geometry (Scene* scene, Type type, size_t numPrimitives, size_t numTimeSteps, RTCGeometryFlags flags);
  31. /*! Geometry destructor */
  32. virtual ~Geometry();
  33. /*! updates intersection filter function counts in scene */
  34. void updateIntersectionFilters(bool enable);
  35. public:
  36. /*! tests if geometry is enabled */
  37. __forceinline bool isEnabled() const { return numPrimitives && enabled; }
  38. /*! tests if geometry is disabled */
  39. __forceinline bool isDisabled() const { return !isEnabled(); }
  40. /*! tests if geomery is used by any instance (including world space instance) */
  41. __forceinline bool isUsed() const { return used; }
  42. /*! tests if geometry is used by any non-world space instance */
  43. __forceinline bool isInstanced() const { return used-enabled; }
  44. /*! tests if geometry is modified */
  45. __forceinline bool isModified() const { return numPrimitives && modified; }
  46. /*! clears modified flag */
  47. __forceinline void clearModified() { modified = false; }
  48. /*! test if this is a static geometry */
  49. __forceinline bool isStatic() const { return flags == RTC_GEOMETRY_STATIC; }
  50. /*! test if this is a deformable geometry */
  51. __forceinline bool isDeformable() const { return flags == RTC_GEOMETRY_DEFORMABLE; }
  52. /*! test if this is a dynamic geometry */
  53. __forceinline bool isDynamic() const { return flags == RTC_GEOMETRY_DYNAMIC; }
  54. /*! returns geometry type */
  55. __forceinline Type getType() const { return type; }
  56. /*! returns number of primitives */
  57. __forceinline size_t size() const { return numPrimitives; }
  58. /*! sets the number of primitives */
  59. __forceinline void setNumPrimitives(size_t numPrimitives_in)
  60. {
  61. if ((ssize_t)numPrimitives_in == -1) return;
  62. if (numPrimitives_in == numPrimitives) return;
  63. numPrimitives = numPrimitives_in;
  64. numPrimitivesChanged = true;
  65. }
  66. /*! for all geometries */
  67. public:
  68. /*! Enable geometry. */
  69. virtual void enable ();
  70. /*! Update geometry. */
  71. virtual void update ();
  72. /*! Update geometry buffer. */
  73. virtual void updateBuffer (RTCBufferType type) {
  74. update(); // update everything for geometries not supporting this call
  75. }
  76. /*! Disable geometry. */
  77. virtual void disable ();
  78. /*! Free buffers that are unused */
  79. virtual void immutable () {}
  80. /*! Verify the geometry */
  81. virtual bool verify () { return true; }
  82. /*! called if geometry is switching from disabled to enabled state */
  83. virtual void enabling() = 0;
  84. /*! called if geometry is switching from enabled to disabled state */
  85. virtual void disabling() = 0;
  86. /*! called before every build */
  87. virtual void preCommit();
  88. /*! called after every build */
  89. virtual void postCommit();
  90. /*! sets constant tessellation rate for the geometry */
  91. virtual void setTessellationRate(float N) {
  92. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  93. }
  94. /*! Set user data pointer. */
  95. virtual void setUserData (void* ptr);
  96. /*! Get user data pointer. */
  97. __forceinline void* getUserData() const {
  98. return userPtr;
  99. }
  100. /*! interpolates user data to the specified u/v location */
  101. virtual void interpolate(unsigned primID, float u, float v, RTCBufferType buffer, float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv, size_t numFloats) {
  102. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  103. }
  104. /*! interpolates user data to the specified u/v locations */
  105. virtual void interpolateN(const void* valid_i, const unsigned* primIDs, const float* u, const float* v, size_t numUVs,
  106. RTCBufferType buffer, float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv, size_t numFloats);
  107. /*! for subdivision surfaces only */
  108. public:
  109. virtual void setSubdivisionMode (unsigned topologyID, RTCSubdivisionMode mode) {
  110. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  111. }
  112. virtual void setIndexBuffer(RTCBufferType vertexBuffer, RTCBufferType indexBuffer) {
  113. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  114. }
  115. /*! for triangle meshes and bezier curves only */
  116. public:
  117. /*! Sets ray mask. */
  118. virtual void setMask (unsigned mask) {
  119. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  120. }
  121. /*! Maps specified buffer. */
  122. virtual void* map(RTCBufferType type) {
  123. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  124. return nullptr;
  125. }
  126. /*! Unmap specified buffer. */
  127. virtual void unmap(RTCBufferType type) {
  128. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  129. }
  130. /*! Sets specified buffer. */
  131. virtual void setBuffer(RTCBufferType type, void* ptr, size_t offset, size_t stride, size_t size) {
  132. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  133. }
  134. /*! Set displacement function. */
  135. virtual void setDisplacementFunction (RTCDisplacementFunc filter, RTCBounds* bounds) {
  136. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  137. }
  138. /*! Set displacement function. */
  139. virtual void setDisplacementFunction2 (RTCDisplacementFunc2 filter, RTCBounds* bounds) {
  140. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  141. }
  142. /*! Set intersection filter function for single rays. */
  143. virtual void setIntersectionFilterFunction (RTCFilterFunc filter, bool ispc = false);
  144. /*! Set intersection filter function for ray packets of size 4. */
  145. virtual void setIntersectionFilterFunction4 (RTCFilterFunc4 filter4, bool ispc = false);
  146. /*! Set intersection filter function for ray packets of size 8. */
  147. virtual void setIntersectionFilterFunction8 (RTCFilterFunc8 filter8, bool ispc = false);
  148. /*! Set intersection filter function for ray packets of size 16. */
  149. virtual void setIntersectionFilterFunction16 (RTCFilterFunc16 filter16, bool ispc = false);
  150. /*! Set intersection filter function for ray packets of size N. */
  151. virtual void setIntersectionFilterFunctionN (RTCFilterFuncN filterN);
  152. /*! Set occlusion filter function for single rays. */
  153. virtual void setOcclusionFilterFunction (RTCFilterFunc filter, bool ispc = false);
  154. /*! Set occlusion filter function for ray packets of size 4. */
  155. virtual void setOcclusionFilterFunction4 (RTCFilterFunc4 filter4, bool ispc = false);
  156. /*! Set occlusion filter function for ray packets of size 8. */
  157. virtual void setOcclusionFilterFunction8 (RTCFilterFunc8 filter8, bool ispc = false);
  158. /*! Set occlusion filter function for ray packets of size 16. */
  159. virtual void setOcclusionFilterFunction16 (RTCFilterFunc16 filter16, bool ispc = false);
  160. /*! Set occlusion filter function for ray packets of size N. */
  161. virtual void setOcclusionFilterFunctionN (RTCFilterFuncN filterN);
  162. /*! for instances only */
  163. public:
  164. /*! Sets transformation of the instance */
  165. virtual void setTransform(const AffineSpace3fa& transform, size_t timeStep) {
  166. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  167. }
  168. /*! for user geometries only */
  169. public:
  170. /*! Set bounds function. */
  171. virtual void setBoundsFunction (RTCBoundsFunc bounds) {
  172. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  173. }
  174. /*! Set bounds function. */
  175. virtual void setBoundsFunction2 (RTCBoundsFunc2 bounds, void* userPtr) {
  176. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  177. }
  178. /*! Set bounds function. */
  179. virtual void setBoundsFunction3 (RTCBoundsFunc3 bounds, void* userPtr) {
  180. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  181. }
  182. /*! Set intersect function for single rays. */
  183. virtual void setIntersectFunction (RTCIntersectFunc intersect, bool ispc = false) {
  184. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  185. }
  186. /*! Set intersect function for ray packets of size 4. */
  187. virtual void setIntersectFunction4 (RTCIntersectFunc4 intersect4, bool ispc = false) {
  188. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  189. }
  190. /*! Set intersect function for ray packets of size 8. */
  191. virtual void setIntersectFunction8 (RTCIntersectFunc8 intersect8, bool ispc = false) {
  192. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  193. }
  194. /*! Set intersect function for ray packets of size 16. */
  195. virtual void setIntersectFunction16 (RTCIntersectFunc16 intersect16, bool ispc = false) {
  196. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  197. }
  198. /*! Set intersect function for streams of single rays. */
  199. virtual void setIntersectFunction1Mp (RTCIntersectFunc1Mp intersect) {
  200. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  201. }
  202. /*! Set intersect function for ray packets of size N. */
  203. virtual void setIntersectFunctionN (RTCIntersectFuncN intersect) {
  204. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  205. }
  206. /*! Set occlusion function for single rays. */
  207. virtual void setOccludedFunction (RTCOccludedFunc occluded, bool ispc = false) {
  208. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  209. }
  210. /*! Set occlusion function for ray packets of size 4. */
  211. virtual void setOccludedFunction4 (RTCOccludedFunc4 occluded4, bool ispc = false) {
  212. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  213. }
  214. /*! Set occlusion function for ray packets of size 8. */
  215. virtual void setOccludedFunction8 (RTCOccludedFunc8 occluded8, bool ispc = false) {
  216. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  217. }
  218. /*! Set occlusion function for ray packets of size 16. */
  219. virtual void setOccludedFunction16 (RTCOccludedFunc16 occluded16, bool ispc = false) {
  220. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  221. }
  222. /*! Set occlusion function for streams of single rays. */
  223. virtual void setOccludedFunction1Mp (RTCOccludedFunc1Mp occluded) {
  224. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  225. }
  226. /*! Set occlusion function for ray packets of size N. */
  227. virtual void setOccludedFunctionN (RTCOccludedFuncN occluded) {
  228. throw_RTCError(RTC_INVALID_OPERATION,"operation not supported for this geometry");
  229. }
  230. /*! returns number of time segments */
  231. __forceinline unsigned numTimeSegments () const {
  232. return numTimeSteps-1;
  233. }
  234. public:
  235. __forceinline bool hasIntersectionFilter1() const { return (hasIntersectionFilterMask & (HAS_FILTER1 | HAS_FILTERN)) != 0; }
  236. __forceinline bool hasOcclusionFilter1 () const { return (hasOcclusionFilterMask & (HAS_FILTER1 | HAS_FILTERN)) != 0; }
  237. template<typename simd> __forceinline bool hasIntersectionFilter() const;
  238. template<typename simd> __forceinline bool hasOcclusionFilter() const;
  239. template<typename simd> __forceinline bool hasISPCIntersectionFilter() const;
  240. template<typename simd> __forceinline bool hasISPCOcclusionFilter() const;
  241. public:
  242. /*! calculates the linear bounds of a primitive at the itimeGlobal'th time segment */
  243. template<typename BoundsFunc>
  244. __forceinline static LBBox3fa linearBounds(const BoundsFunc& bounds, size_t itimeGlobal, size_t numTimeStepsGlobal, size_t numTimeSteps)
  245. {
  246. if (numTimeStepsGlobal == numTimeSteps)
  247. {
  248. const BBox3fa bounds0 = bounds(itimeGlobal+0);
  249. const BBox3fa bounds1 = bounds(itimeGlobal+1);
  250. return LBBox3fa(bounds0, bounds1);
  251. }
  252. const int timeSegments = int(numTimeSteps-1);
  253. const int timeSegmentsGlobal = int(numTimeStepsGlobal-1);
  254. const float invTimeSegmentsGlobal = rcp(float(timeSegmentsGlobal));
  255. const int itimeScaled = int(itimeGlobal) * timeSegments;
  256. const int itime0 = itimeScaled / timeSegmentsGlobal;
  257. const int rtime0 = itimeScaled % timeSegmentsGlobal;
  258. const float ftime0 = float(rtime0) * invTimeSegmentsGlobal;
  259. const int rtime1 = rtime0 + timeSegments;
  260. if (rtime1 <= timeSegmentsGlobal)
  261. {
  262. const BBox3fa b0 = bounds(itime0+0);
  263. const BBox3fa b1 = bounds(itime0+1);
  264. const float ftime1 = float(rtime1) * invTimeSegmentsGlobal;
  265. return LBBox3fa(lerp(b0, b1, ftime0), lerp(b0, b1, ftime1));
  266. }
  267. const BBox3fa b0 = bounds(itime0+0);
  268. const BBox3fa b1 = bounds(itime0+1);
  269. const BBox3fa b2 = bounds(itime0+2);
  270. const float ftime1 = float(rtime1-timeSegmentsGlobal) * invTimeSegmentsGlobal;
  271. BBox3fa bounds0 = lerp(b0, b1, ftime0);
  272. BBox3fa bounds1 = lerp(b1, b2, ftime1);
  273. const BBox3fa b1Lerp = lerp(bounds0, bounds1, float(timeSegmentsGlobal-rtime0) * rcp(float(timeSegments)));
  274. bounds0.lower = min(bounds0.lower, bounds0.lower - (b1Lerp.lower - b1.lower));
  275. bounds1.lower = min(bounds1.lower, bounds1.lower - (b1Lerp.lower - b1.lower));
  276. bounds0.upper = max(bounds0.upper, bounds0.upper + (b1.upper - b1Lerp.upper));
  277. bounds1.upper = max(bounds1.upper, bounds1.upper + (b1.upper - b1Lerp.upper));
  278. return LBBox3fa(bounds0, bounds1);
  279. }
  280. /*! calculates the linear bounds of a primitive at the itimeGlobal'th time segment, if it's valid */
  281. template<typename BoundsFunc>
  282. __forceinline static bool linearBounds(const BoundsFunc& bounds, size_t itimeGlobal, size_t numTimeStepsGlobal, size_t numTimeSteps, LBBox3fa& lbbox)
  283. {
  284. if (numTimeStepsGlobal == numTimeSteps)
  285. {
  286. BBox3fa bounds0; if (unlikely(!bounds(itimeGlobal+0, bounds0))) return false;
  287. BBox3fa bounds1; if (unlikely(!bounds(itimeGlobal+1, bounds1))) return false;
  288. lbbox = LBBox3fa(bounds0, bounds1);
  289. return true;
  290. }
  291. const int timeSegments = int(numTimeSteps-1);
  292. const int timeSegmentsGlobal = int(numTimeStepsGlobal-1);
  293. const float invTimeSegmentsGlobal = rcp(float(timeSegmentsGlobal));
  294. const int itimeScaled = int(itimeGlobal) * timeSegments;
  295. const int itime0 = itimeScaled / timeSegmentsGlobal;
  296. const int rtime0 = itimeScaled % timeSegmentsGlobal;
  297. const float ftime0 = float(rtime0) * invTimeSegmentsGlobal;
  298. const int rtime1 = rtime0 + timeSegments;
  299. if (rtime1 <= timeSegmentsGlobal)
  300. {
  301. BBox3fa b0; if (unlikely(!bounds(itime0+0, b0))) return false;
  302. BBox3fa b1; if (unlikely(!bounds(itime0+1, b1))) return false;
  303. const float ftime1 = float(rtime1) * invTimeSegmentsGlobal;
  304. lbbox = LBBox3fa(lerp(b0, b1, ftime0), lerp(b0, b1, ftime1));
  305. return true;
  306. }
  307. BBox3fa b0; if (unlikely(!bounds(itime0+0, b0))) return false;
  308. BBox3fa b1; if (unlikely(!bounds(itime0+1, b1))) return false;
  309. BBox3fa b2; if (unlikely(!bounds(itime0+2, b2))) return false;
  310. const float ftime1 = float(rtime1-timeSegmentsGlobal) * invTimeSegmentsGlobal;
  311. BBox3fa bounds0 = lerp(b0, b1, ftime0);
  312. BBox3fa bounds1 = lerp(b1, b2, ftime1);
  313. const BBox3fa b1Lerp = lerp(bounds0, bounds1, float(timeSegmentsGlobal-rtime0) * rcp(float(timeSegments)));
  314. bounds0.lower = min(bounds0.lower, bounds0.lower - (b1Lerp.lower - b1.lower));
  315. bounds1.lower = min(bounds1.lower, bounds1.lower - (b1Lerp.lower - b1.lower));
  316. bounds0.upper = max(bounds0.upper, bounds0.upper + (b1.upper - b1Lerp.upper));
  317. bounds1.upper = max(bounds1.upper, bounds1.upper + (b1.upper - b1Lerp.upper));
  318. lbbox = LBBox3fa(bounds0, bounds1);
  319. return true;
  320. }
  321. /*! calculates the build bounds of a primitive at the itimeGlobal'th time segment, if it's valid */
  322. template<typename BoundsFunc>
  323. __forceinline static bool buildBounds(const BoundsFunc& bounds, size_t itimeGlobal, size_t numTimeStepsGlobal, size_t numTimeSteps, BBox3fa& bbox)
  324. {
  325. LBBox3fa lbbox;
  326. if (!linearBounds(bounds, itimeGlobal, numTimeStepsGlobal, numTimeSteps, lbbox))
  327. return false;
  328. bbox = 0.5f * (lbbox.bounds0 + lbbox.bounds1);
  329. return true;
  330. }
  331. /*! checks if a primitive is valid at the itimeGlobal'th time segment */
  332. template<typename ValidFunc>
  333. __forceinline static bool validLinearBounds(const ValidFunc& valid, size_t itimeGlobal, size_t numTimeStepsGlobal, size_t numTimeSteps)
  334. {
  335. if (numTimeStepsGlobal == numTimeSteps)
  336. {
  337. if (unlikely(!valid(itimeGlobal+0))) return false;
  338. if (unlikely(!valid(itimeGlobal+1))) return false;
  339. return true;
  340. }
  341. const int timeSegments = int(numTimeSteps-1);
  342. const int timeSegmentsGlobal = int(numTimeStepsGlobal-1);
  343. const int itimeScaled = int(itimeGlobal) * timeSegments;
  344. const int itime0 = itimeScaled / timeSegmentsGlobal;
  345. const int rtime0 = itimeScaled % timeSegmentsGlobal;
  346. const int rtime1 = rtime0 + timeSegments;
  347. if (rtime1 <= timeSegmentsGlobal)
  348. {
  349. if (unlikely(!valid(itime0+0))) return false;
  350. if (unlikely(!valid(itime0+1))) return false;
  351. return true;
  352. }
  353. if (unlikely(!valid(itime0+0))) return false;
  354. if (unlikely(!valid(itime0+1))) return false;
  355. if (unlikely(!valid(itime0+2))) return false;
  356. return true;
  357. }
  358. public:
  359. Scene* parent; //!< pointer to scene this mesh belongs to
  360. unsigned id; //!< internal geometry ID
  361. Type type; //!< geometry type
  362. size_t numPrimitives; //!< number of primitives of this geometry
  363. bool numPrimitivesChanged; //!< true if number of primitives changed
  364. unsigned numTimeSteps; //!< number of time steps
  365. float fnumTimeSegments; //!< number of time segments (precalculation)
  366. RTCGeometryFlags flags; //!< flags of geometry
  367. bool enabled; //!< true if geometry is enabled
  368. bool modified; //!< true if geometry is modified
  369. void* userPtr; //!< user pointer
  370. unsigned mask; //!< for masking out geometry
  371. std::atomic<size_t> used; //!< counts by how many enabled instances this geometry is used
  372. public:
  373. RTCFilterFunc intersectionFilter1;
  374. RTCFilterFunc occlusionFilter1;
  375. RTCFilterFunc4 intersectionFilter4;
  376. RTCFilterFunc4 occlusionFilter4;
  377. RTCFilterFunc8 intersectionFilter8;
  378. RTCFilterFunc8 occlusionFilter8;
  379. RTCFilterFunc16 intersectionFilter16;
  380. RTCFilterFunc16 occlusionFilter16;
  381. RTCFilterFuncN intersectionFilterN;
  382. RTCFilterFuncN occlusionFilterN;
  383. public:
  384. enum { HAS_FILTER1 = 1, HAS_FILTER4 = 2, HAS_FILTER8 = 4, HAS_FILTER16 = 8, HAS_FILTERN = 16 };
  385. int hasIntersectionFilterMask;
  386. int hasOcclusionFilterMask;
  387. int ispcIntersectionFilterMask;
  388. int ispcOcclusionFilterMask;
  389. };
  390. #if defined(__SSE__)
  391. template<> __forceinline bool Geometry::hasIntersectionFilter<vfloat4>() const { return (hasIntersectionFilterMask & (HAS_FILTER4 | HAS_FILTERN)) != 0; }
  392. template<> __forceinline bool Geometry::hasOcclusionFilter <vfloat4>() const { return (hasOcclusionFilterMask & (HAS_FILTER4 | HAS_FILTERN)) != 0; }
  393. template<> __forceinline bool Geometry::hasISPCIntersectionFilter<vfloat4>() const { return (ispcIntersectionFilterMask & HAS_FILTER4) != 0; }
  394. template<> __forceinline bool Geometry::hasISPCOcclusionFilter <vfloat4>() const { return (ispcOcclusionFilterMask & HAS_FILTER4) != 0; }
  395. #endif
  396. #if defined(__AVX__)
  397. template<> __forceinline bool Geometry::hasIntersectionFilter<vfloat8>() const { return (hasIntersectionFilterMask & (HAS_FILTER8 | HAS_FILTERN)) != 0; }
  398. template<> __forceinline bool Geometry::hasOcclusionFilter <vfloat8>() const { return (hasOcclusionFilterMask & (HAS_FILTER8 | HAS_FILTERN)) != 0; }
  399. template<> __forceinline bool Geometry::hasISPCIntersectionFilter<vfloat8>() const { return (ispcIntersectionFilterMask & HAS_FILTER8) != 0; }
  400. template<> __forceinline bool Geometry::hasISPCOcclusionFilter <vfloat8>() const { return (ispcOcclusionFilterMask & HAS_FILTER8) != 0; }
  401. #endif
  402. #if defined(__AVX512F__)
  403. template<> __forceinline bool Geometry::hasIntersectionFilter<vfloat16>() const { return (hasIntersectionFilterMask & (HAS_FILTER16 | HAS_FILTERN)) != 0; }
  404. template<> __forceinline bool Geometry::hasOcclusionFilter <vfloat16>() const { return (hasOcclusionFilterMask & (HAS_FILTER16 | HAS_FILTERN)) != 0; }
  405. template<> __forceinline bool Geometry::hasISPCIntersectionFilter<vfloat16>() const { return (ispcIntersectionFilterMask & HAS_FILTER16) != 0; }
  406. template<> __forceinline bool Geometry::hasISPCOcclusionFilter <vfloat16>() const { return (ispcOcclusionFilterMask & HAS_FILTER16) != 0; }
  407. #endif
  408. /* calculate time segment itime and fractional time ftime */
  409. __forceinline int getTimeSegment(float time, float numTimeSegments, float& ftime)
  410. {
  411. const float timeScaled = time * numTimeSegments;
  412. const float itimef = clamp(floor(timeScaled), 0.0f, numTimeSegments-1.0f);
  413. ftime = timeScaled - itimef;
  414. return int(itimef);
  415. }
  416. template<int N>
  417. __forceinline vint<N> getTimeSegment(const vfloat<N>& time, const vfloat<N>& numTimeSegments, vfloat<N>& ftime)
  418. {
  419. const vfloat<N> timeScaled = time * numTimeSegments;
  420. const vfloat<N> itimef = clamp(floor(timeScaled), vfloat<N>(zero), numTimeSegments-1.0f);
  421. ftime = timeScaled - itimef;
  422. return vint<N>(itimef);
  423. }
  424. }