scene_instance.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  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 AffineSpace3fa getTransform(size_t, float time) override;
  44. virtual void setMask (unsigned mask) override;
  45. virtual void build() {}
  46. virtual void addElementsToCount (GeometryCounts & counts) const override;
  47. virtual void commit() override;
  48. public:
  49. /*! calculates the bounds of instance */
  50. __forceinline BBox3fa bounds(size_t i) const {
  51. assert(i == 0);
  52. if (unlikely(gsubtype == GTY_SUBTYPE_INSTANCE_QUATERNION))
  53. return xfmBounds(quaternionDecompositionToAffineSpace(local2world[0]),object->bounds.bounds());
  54. return xfmBounds(local2world[0],object->bounds.bounds());
  55. }
  56. /*! gets the bounds of the instanced scene */
  57. __forceinline BBox3fa getObjectBounds(size_t itime) const {
  58. return object->getBounds(timeStep(itime));
  59. }
  60. /*! calculates the bounds of instance */
  61. __forceinline BBox3fa bounds(size_t i, size_t itime) const {
  62. assert(i == 0);
  63. if (unlikely(gsubtype == GTY_SUBTYPE_INSTANCE_QUATERNION))
  64. return xfmBounds(quaternionDecompositionToAffineSpace(local2world[itime]),getObjectBounds(itime));
  65. return xfmBounds(local2world[itime],getObjectBounds(itime));
  66. }
  67. /*! calculates the linear bounds of the i'th primitive for the specified time range */
  68. __forceinline LBBox3fa linearBounds(size_t i, const BBox1f& dt) const {
  69. assert(i == 0);
  70. LBBox3fa lbbox = nonlinearBounds(dt, time_range, fnumTimeSegments);
  71. return lbbox;
  72. }
  73. /*! calculates the build bounds of the i'th item, if it's valid */
  74. __forceinline bool buildBounds(size_t i, BBox3fa* bbox = nullptr) const
  75. {
  76. assert(i==0);
  77. const BBox3fa b = bounds(i);
  78. if (bbox) *bbox = b;
  79. return isvalid(b);
  80. }
  81. /*! calculates the build bounds of the i'th item at the itime'th time segment, if it's valid */
  82. __forceinline bool buildBounds(size_t i, size_t itime, BBox3fa& bbox) const
  83. {
  84. assert(i==0);
  85. const LBBox3fa bounds = linearBounds(i,itime);
  86. bbox = bounds.bounds ();
  87. return isvalid(bounds);
  88. }
  89. /* gets version info of topology */
  90. unsigned int getTopologyVersion() const {
  91. return numPrimitives;
  92. }
  93. /* returns true if topology changed */
  94. bool topologyChanged(unsigned int otherVersion) const {
  95. return numPrimitives != otherVersion;
  96. }
  97. /*! check if the i'th primitive is valid between the specified time range */
  98. __forceinline bool valid(size_t i, const range<size_t>& itime_range) const
  99. {
  100. assert(i == 0);
  101. for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
  102. if (!isvalid(bounds(i,itime))) return false;
  103. return true;
  104. }
  105. __forceinline AffineSpace3fa getLocal2World() const
  106. {
  107. if (unlikely(gsubtype == GTY_SUBTYPE_INSTANCE_QUATERNION))
  108. return quaternionDecompositionToAffineSpace(local2world[0]);
  109. return local2world[0];
  110. }
  111. __forceinline AffineSpace3fa getLocal2World(float t) const
  112. {
  113. if (numTimeSegments() > 0) {
  114. float ftime; const unsigned int itime = timeSegment(t, ftime);
  115. if (unlikely(gsubtype == GTY_SUBTYPE_INSTANCE_QUATERNION))
  116. return slerp(local2world[itime+0],local2world[itime+1],ftime);
  117. return lerp(local2world[itime+0],local2world[itime+1],ftime);
  118. }
  119. return getLocal2World();
  120. }
  121. __forceinline AffineSpace3fa getWorld2Local() const {
  122. return world2local0;
  123. }
  124. __forceinline AffineSpace3fa getWorld2Local(float t) const {
  125. if (numTimeSegments() > 0)
  126. return rcp(getLocal2World(t));
  127. return getWorld2Local();
  128. }
  129. template<int K>
  130. __forceinline AffineSpace3vf<K> getWorld2Local(const vbool<K>& valid, const vfloat<K>& t) const
  131. {
  132. if (unlikely(gsubtype == GTY_SUBTYPE_INSTANCE_QUATERNION))
  133. return getWorld2LocalSlerp<K>(valid, t);
  134. return getWorld2LocalLerp<K>(valid, t);
  135. }
  136. __forceinline float projectedPrimitiveArea(const size_t i) const {
  137. return area(bounds(i));
  138. }
  139. private:
  140. template<int K>
  141. __forceinline AffineSpace3vf<K> getWorld2LocalSlerp(const vbool<K>& valid, const vfloat<K>& t) const
  142. {
  143. vfloat<K> ftime;
  144. const vint<K> itime_k = timeSegment<K>(t, ftime);
  145. assert(any(valid));
  146. const size_t index = bsf(movemask(valid));
  147. const int itime = itime_k[index];
  148. if (likely(all(valid, itime_k == vint<K>(itime)))) {
  149. return rcp(slerp(AffineSpace3vff<K>(local2world[itime+0]),
  150. AffineSpace3vff<K>(local2world[itime+1]),
  151. ftime));
  152. }
  153. else {
  154. AffineSpace3vff<K> space0,space1;
  155. vbool<K> valid1 = valid;
  156. while (any(valid1)) {
  157. vbool<K> valid2;
  158. const int itime = next_unique(valid1, itime_k, valid2);
  159. space0 = select(valid2, AffineSpace3vff<K>(local2world[itime+0]), space0);
  160. space1 = select(valid2, AffineSpace3vff<K>(local2world[itime+1]), space1);
  161. }
  162. return rcp(slerp(space0, space1, ftime));
  163. }
  164. }
  165. template<int K>
  166. __forceinline AffineSpace3vf<K> getWorld2LocalLerp(const vbool<K>& valid, const vfloat<K>& t) const
  167. {
  168. vfloat<K> ftime;
  169. const vint<K> itime_k = timeSegment<K>(t, ftime);
  170. assert(any(valid));
  171. const size_t index = bsf(movemask(valid));
  172. const int itime = itime_k[index];
  173. if (likely(all(valid, itime_k == vint<K>(itime)))) {
  174. return rcp(lerp(AffineSpace3vf<K>((AffineSpace3fa)local2world[itime+0]),
  175. AffineSpace3vf<K>((AffineSpace3fa)local2world[itime+1]),
  176. ftime));
  177. } else {
  178. AffineSpace3vf<K> space0,space1;
  179. vbool<K> valid1 = valid;
  180. while (any(valid1)) {
  181. vbool<K> valid2;
  182. const int itime = next_unique(valid1, itime_k, valid2);
  183. space0 = select(valid2, AffineSpace3vf<K>((AffineSpace3fa)local2world[itime+0]), space0);
  184. space1 = select(valid2, AffineSpace3vf<K>((AffineSpace3fa)local2world[itime+1]), space1);
  185. }
  186. return rcp(lerp(space0, space1, ftime));
  187. }
  188. }
  189. public:
  190. Accel* object; //!< pointer to instanced acceleration structure
  191. AffineSpace3ff* local2world; //!< transformation from local space to world space for each timestep (either normal matrix or quaternion decomposition)
  192. AffineSpace3fa world2local0; //!< transformation from world space to local space for timestep 0
  193. };
  194. namespace isa
  195. {
  196. struct InstanceISA : public Instance
  197. {
  198. InstanceISA (Device* device)
  199. : Instance(device) {}
  200. LBBox3fa vlinearBounds(size_t primID, const BBox1f& time_range) const {
  201. return linearBounds(primID,time_range);
  202. }
  203. PrimInfo createPrimRefArray(PrimRef* prims, const range<size_t>& r, size_t k, unsigned int geomID) const
  204. {
  205. assert(r.begin() == 0);
  206. assert(r.end() == 1);
  207. PrimInfo pinfo(empty);
  208. BBox3fa b = empty;
  209. if (!buildBounds(0,&b)) return pinfo;
  210. // const BBox3fa b = bounds(0);
  211. // if (!isvalid(b)) return pinfo;
  212. const PrimRef prim(b,geomID,unsigned(0));
  213. pinfo.add_center2(prim);
  214. prims[k++] = prim;
  215. return pinfo;
  216. }
  217. PrimInfo createPrimRefArrayMB(mvector<PrimRef>& prims, size_t itime, const range<size_t>& r, size_t k, unsigned int geomID) const
  218. {
  219. assert(r.begin() == 0);
  220. assert(r.end() == 1);
  221. PrimInfo pinfo(empty);
  222. BBox3fa b = empty;
  223. if (!buildBounds(0,&b)) return pinfo;
  224. // if (!valid(0,range<size_t>(itime))) return pinfo;
  225. // const PrimRef prim(linearBounds(0,itime).bounds(),geomID,unsigned(0));
  226. const PrimRef prim(b,geomID,unsigned(0));
  227. pinfo.add_center2(prim);
  228. prims[k++] = prim;
  229. return pinfo;
  230. }
  231. PrimInfo createPrimRefArrayMB(PrimRef* prims, const BBox1f& time_range, const range<size_t>& r, size_t k, unsigned int geomID) const
  232. {
  233. assert(r.begin() == 0);
  234. assert(r.end() == 1);
  235. PrimInfo pinfo(empty);
  236. const BBox1f t0t1 = intersect(getTimeRange(), time_range);
  237. if (t0t1.empty()) return pinfo;
  238. const BBox3fa bounds = linearBounds(0, t0t1).bounds();
  239. const PrimRef prim(bounds, geomID, unsigned(0));
  240. pinfo.add_center2(prim);
  241. prims[k++] = prim;
  242. return pinfo;
  243. }
  244. PrimInfoMB createPrimRefMBArray(mvector<PrimRefMB>& prims, const BBox1f& t0t1, const range<size_t>& r, size_t k, unsigned int geomID) const
  245. {
  246. assert(r.begin() == 0);
  247. assert(r.end() == 1);
  248. PrimInfoMB pinfo(empty);
  249. if (!valid(0, timeSegmentRange(t0t1))) return pinfo;
  250. const PrimRefMB prim(linearBounds(0,t0t1),this->numTimeSegments(),this->time_range,this->numTimeSegments(),geomID,unsigned(0));
  251. pinfo.add_primref(prim);
  252. prims[k++] = prim;
  253. return pinfo;
  254. }
  255. };
  256. }
  257. DECLARE_ISA_FUNCTION(Instance*, createInstance, Device*);
  258. }