scene_instance.h 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #include "geometry.h"
  5. #include "accel.h"
  6. namespace embree
  7. {
  8. struct MotionDerivativeCoefficients;
  9. /*! Instanced acceleration structure */
  10. struct Instance : public Geometry
  11. {
  12. ALIGNED_STRUCT_(16);
  13. static const Geometry::GTypeMask geom_type = Geometry::MTY_INSTANCE;
  14. public:
  15. Instance (Device* device, Accel* object = nullptr, unsigned int numTimeSteps = 1);
  16. ~Instance();
  17. private:
  18. Instance (const Instance& other) DELETED; // do not implement
  19. Instance& operator= (const Instance& other) DELETED; // do not implement
  20. private:
  21. LBBox3fa nonlinearBounds(const BBox1f& time_range_in,
  22. const BBox1f& geom_time_range,
  23. float geom_time_segments) const;
  24. BBox3fa boundSegment(size_t itime,
  25. BBox3fa const& obbox0, BBox3fa const& obbox1,
  26. BBox3fa const& bbox0, BBox3fa const& bbox1,
  27. float t_min, float t_max) const;
  28. /* calculates the (correct) interpolated bounds */
  29. __forceinline BBox3fa bounds(size_t itime0, size_t itime1, float f) const
  30. {
  31. if (unlikely(gsubtype == GTY_SUBTYPE_INSTANCE_QUATERNION))
  32. return xfmBounds(slerp(local2world[itime0], local2world[itime1], f),
  33. lerp(getObjectBounds(itime0), getObjectBounds(itime1), f));
  34. return xfmBounds(lerp(local2world[itime0], local2world[itime1], f),
  35. lerp(getObjectBounds(itime0), getObjectBounds(itime1), f));
  36. }
  37. public:
  38. virtual void setNumTimeSteps (unsigned int numTimeSteps) override;
  39. virtual void setInstancedScene(const Ref<Scene>& scene) override;
  40. virtual void setTransform(const AffineSpace3fa& local2world, unsigned int timeStep) override;
  41. virtual void setQuaternionDecomposition(const AffineSpace3ff& qd, unsigned int timeStep) override;
  42. virtual AffineSpace3fa getTransform(float time) override;
  43. virtual void setMask (unsigned mask) override;
  44. virtual void build() {}
  45. virtual void addElementsToCount (GeometryCounts & counts) const override;
  46. virtual void commit() override;
  47. public:
  48. /*! calculates the bounds of instance */
  49. __forceinline BBox3fa bounds(size_t i) const {
  50. assert(i == 0);
  51. if (unlikely(gsubtype == GTY_SUBTYPE_INSTANCE_QUATERNION))
  52. return xfmBounds(quaternionDecompositionToAffineSpace(local2world[0]),object->bounds.bounds());
  53. return xfmBounds(local2world[0],object->bounds.bounds());
  54. }
  55. /*! gets the bounds of the instanced scene */
  56. __forceinline BBox3fa getObjectBounds(size_t itime) const {
  57. return object->getBounds(timeStep(itime));
  58. }
  59. /*! calculates the bounds of instance */
  60. __forceinline BBox3fa bounds(size_t i, size_t itime) const {
  61. assert(i == 0);
  62. if (unlikely(gsubtype == GTY_SUBTYPE_INSTANCE_QUATERNION))
  63. return xfmBounds(quaternionDecompositionToAffineSpace(local2world[itime]),getObjectBounds(itime));
  64. return xfmBounds(local2world[itime],getObjectBounds(itime));
  65. }
  66. /*! calculates the linear bounds of the i'th primitive for the specified time range */
  67. __forceinline LBBox3fa linearBounds(size_t i, const BBox1f& dt) const {
  68. assert(i == 0);
  69. LBBox3fa lbbox = nonlinearBounds(dt, time_range, fnumTimeSegments);
  70. return lbbox;
  71. }
  72. /*! calculates the build bounds of the i'th item, if it's valid */
  73. __forceinline bool buildBounds(size_t i, BBox3fa* bbox = nullptr) const
  74. {
  75. assert(i==0);
  76. const BBox3fa b = bounds(i);
  77. if (bbox) *bbox = b;
  78. return isvalid(b);
  79. }
  80. /*! calculates the build bounds of the i'th item at the itime'th time segment, if it's valid */
  81. __forceinline bool buildBounds(size_t i, size_t itime, BBox3fa& bbox) const
  82. {
  83. assert(i==0);
  84. const LBBox3fa bounds = linearBounds(i,itime);
  85. bbox = bounds.bounds ();
  86. return isvalid(bounds);
  87. }
  88. /* gets version info of topology */
  89. unsigned int getTopologyVersion() const {
  90. return numPrimitives;
  91. }
  92. /* returns true if topology changed */
  93. bool topologyChanged(unsigned int otherVersion) const {
  94. return numPrimitives != otherVersion;
  95. }
  96. /*! check if the i'th primitive is valid between the specified time range */
  97. __forceinline bool valid(size_t i, const range<size_t>& itime_range) const
  98. {
  99. assert(i == 0);
  100. for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
  101. if (!isvalid(bounds(i,itime))) return false;
  102. return true;
  103. }
  104. __forceinline AffineSpace3fa getLocal2World() const
  105. {
  106. if (unlikely(gsubtype == GTY_SUBTYPE_INSTANCE_QUATERNION))
  107. return quaternionDecompositionToAffineSpace(local2world[0]);
  108. return local2world[0];
  109. }
  110. __forceinline AffineSpace3fa getLocal2World(float t) const
  111. {
  112. float ftime; const unsigned int itime = timeSegment(t, ftime);
  113. if (unlikely(gsubtype == GTY_SUBTYPE_INSTANCE_QUATERNION))
  114. return slerp(local2world[itime+0],local2world[itime+1],ftime);
  115. return lerp(local2world[itime+0],local2world[itime+1],ftime);
  116. }
  117. __forceinline AffineSpace3fa getWorld2Local() const {
  118. return world2local0;
  119. }
  120. __forceinline AffineSpace3fa getWorld2Local(float t) const {
  121. return rcp(getLocal2World(t));
  122. }
  123. template<int K>
  124. __forceinline AffineSpace3vf<K> getWorld2Local(const vbool<K>& valid, const vfloat<K>& t) const
  125. {
  126. if (unlikely(gsubtype == GTY_SUBTYPE_INSTANCE_QUATERNION))
  127. return getWorld2LocalSlerp<K>(valid, t);
  128. return getWorld2LocalLerp<K>(valid, t);
  129. }
  130. private:
  131. template<int K>
  132. __forceinline AffineSpace3vf<K> getWorld2LocalSlerp(const vbool<K>& valid, const vfloat<K>& t) const
  133. {
  134. vfloat<K> ftime;
  135. const vint<K> itime_k = timeSegment<K>(t, ftime);
  136. assert(any(valid));
  137. const size_t index = bsf(movemask(valid));
  138. const int itime = itime_k[index];
  139. if (likely(all(valid, itime_k == vint<K>(itime)))) {
  140. return rcp(slerp(AffineSpace3vff<K>(local2world[itime+0]),
  141. AffineSpace3vff<K>(local2world[itime+1]),
  142. ftime));
  143. }
  144. else {
  145. AffineSpace3vff<K> space0,space1;
  146. vbool<K> valid1 = valid;
  147. while (any(valid1)) {
  148. vbool<K> valid2;
  149. const int itime = next_unique(valid1, itime_k, valid2);
  150. space0 = select(valid2, AffineSpace3vff<K>(local2world[itime+0]), space0);
  151. space1 = select(valid2, AffineSpace3vff<K>(local2world[itime+1]), space1);
  152. }
  153. return rcp(slerp(space0, space1, ftime));
  154. }
  155. }
  156. template<int K>
  157. __forceinline AffineSpace3vf<K> getWorld2LocalLerp(const vbool<K>& valid, const vfloat<K>& t) const
  158. {
  159. vfloat<K> ftime;
  160. const vint<K> itime_k = timeSegment<K>(t, ftime);
  161. assert(any(valid));
  162. const size_t index = bsf(movemask(valid));
  163. const int itime = itime_k[index];
  164. if (likely(all(valid, itime_k == vint<K>(itime)))) {
  165. return rcp(lerp(AffineSpace3vf<K>((AffineSpace3fa)local2world[itime+0]),
  166. AffineSpace3vf<K>((AffineSpace3fa)local2world[itime+1]),
  167. ftime));
  168. } else {
  169. AffineSpace3vf<K> space0,space1;
  170. vbool<K> valid1 = valid;
  171. while (any(valid1)) {
  172. vbool<K> valid2;
  173. const int itime = next_unique(valid1, itime_k, valid2);
  174. space0 = select(valid2, AffineSpace3vf<K>((AffineSpace3fa)local2world[itime+0]), space0);
  175. space1 = select(valid2, AffineSpace3vf<K>((AffineSpace3fa)local2world[itime+1]), space1);
  176. }
  177. return rcp(lerp(space0, space1, ftime));
  178. }
  179. }
  180. public:
  181. Accel* object; //!< pointer to instanced acceleration structure
  182. AffineSpace3ff* local2world; //!< transformation from local space to world space for each timestep (either normal matrix or quaternion decomposition)
  183. AffineSpace3fa world2local0; //!< transformation from world space to local space for timestep 0
  184. };
  185. namespace isa
  186. {
  187. struct InstanceISA : public Instance
  188. {
  189. InstanceISA (Device* device)
  190. : Instance(device) {}
  191. PrimInfo createPrimRefArray(mvector<PrimRef>& prims, const range<size_t>& r, size_t k, unsigned int geomID) const
  192. {
  193. assert(r.begin() == 0);
  194. assert(r.end() == 1);
  195. PrimInfo pinfo(empty);
  196. BBox3fa b = empty;
  197. if (!buildBounds(0,&b)) return pinfo;
  198. // const BBox3fa b = bounds(0);
  199. // if (!isvalid(b)) return pinfo;
  200. const PrimRef prim(b,geomID,unsigned(0));
  201. pinfo.add_center2(prim);
  202. prims[k++] = prim;
  203. return pinfo;
  204. }
  205. PrimInfo createPrimRefArrayMB(mvector<PrimRef>& prims, size_t itime, const range<size_t>& r, size_t k, unsigned int geomID) const
  206. {
  207. assert(r.begin() == 0);
  208. assert(r.end() == 1);
  209. PrimInfo pinfo(empty);
  210. BBox3fa b = empty;
  211. if (!buildBounds(0,&b)) return pinfo;
  212. // if (!valid(0,range<size_t>(itime))) return pinfo;
  213. // const PrimRef prim(linearBounds(0,itime).bounds(),geomID,unsigned(0));
  214. const PrimRef prim(b,geomID,unsigned(0));
  215. pinfo.add_center2(prim);
  216. prims[k++] = prim;
  217. return pinfo;
  218. }
  219. PrimInfoMB createPrimRefMBArray(mvector<PrimRefMB>& prims, const BBox1f& t0t1, const range<size_t>& r, size_t k, unsigned int geomID) const
  220. {
  221. assert(r.begin() == 0);
  222. assert(r.end() == 1);
  223. PrimInfoMB pinfo(empty);
  224. if (!valid(0, timeSegmentRange(t0t1))) return pinfo;
  225. const PrimRefMB prim(linearBounds(0,t0t1),this->numTimeSegments(),this->time_range,this->numTimeSegments(),geomID,unsigned(0));
  226. pinfo.add_primref(prim);
  227. prims[k++] = prim;
  228. return pinfo;
  229. }
  230. };
  231. }
  232. DECLARE_ISA_FUNCTION(Instance*, createInstance, Device*);
  233. }