scene_line_segments.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #include "default.h"
  5. #include "geometry.h"
  6. #include "buffer.h"
  7. namespace embree
  8. {
  9. /*! represents an array of line segments */
  10. struct LineSegments : public Geometry
  11. {
  12. /*! type of this geometry */
  13. static const Geometry::GTypeMask geom_type = Geometry::MTY_CURVE2;
  14. public:
  15. /*! line segments construction */
  16. LineSegments (Device* device, Geometry::GType gtype);
  17. public:
  18. void setMask (unsigned mask);
  19. void setNumTimeSteps (unsigned int numTimeSteps);
  20. void setVertexAttributeCount (unsigned int N);
  21. void setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num);
  22. void* getBuffer(RTCBufferType type, unsigned int slot);
  23. void updateBuffer(RTCBufferType type, unsigned int slot);
  24. void commit();
  25. bool verify ();
  26. void interpolate(const RTCInterpolateArguments* const args);
  27. void setTessellationRate(float N);
  28. void setMaxRadiusScale(float s);
  29. void addElementsToCount (GeometryCounts & counts) const;
  30. template<int N>
  31. void interpolate_impl(const RTCInterpolateArguments* const args)
  32. {
  33. unsigned int primID = args->primID;
  34. float u = args->u;
  35. RTCBufferType bufferType = args->bufferType;
  36. unsigned int bufferSlot = args->bufferSlot;
  37. float* P = args->P;
  38. float* dPdu = args->dPdu;
  39. float* ddPdudu = args->ddPdudu;
  40. unsigned int valueCount = args->valueCount;
  41. /* calculate base pointer and stride */
  42. assert((bufferType == RTC_BUFFER_TYPE_VERTEX && bufferSlot < numTimeSteps) ||
  43. (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE && bufferSlot <= vertexAttribs.size()));
  44. const char* src = nullptr;
  45. size_t stride = 0;
  46. if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE) {
  47. src = vertexAttribs[bufferSlot].getPtr();
  48. stride = vertexAttribs[bufferSlot].getStride();
  49. } else {
  50. src = vertices[bufferSlot].getPtr();
  51. stride = vertices[bufferSlot].getStride();
  52. }
  53. for (unsigned int i=0; i<valueCount; i+=N)
  54. {
  55. const size_t ofs = i*sizeof(float);
  56. const size_t segment = segments[primID];
  57. const vbool<N> valid = vint<N>((int)i)+vint<N>(step) < vint<N>(int(valueCount));
  58. const vfloat<N> p0 = mem<vfloat<N>>::loadu(valid,(float*)&src[(segment+0)*stride+ofs]);
  59. const vfloat<N> p1 = mem<vfloat<N>>::loadu(valid,(float*)&src[(segment+1)*stride+ofs]);
  60. if (P ) mem<vfloat<N>>::storeu(valid,P+i,lerp(p0,p1,u));
  61. if (dPdu ) mem<vfloat<N>>::storeu(valid,dPdu+i,p1-p0);
  62. if (ddPdudu) mem<vfloat<N>>::storeu(valid,dPdu+i,vfloat<N>(zero));
  63. }
  64. }
  65. public:
  66. /*! returns the number of vertices */
  67. __forceinline size_t numVertices() const {
  68. return vertices[0].size();
  69. }
  70. /*! returns the i'th segment */
  71. __forceinline const unsigned int& segment(size_t i) const {
  72. return segments[i];
  73. }
  74. /*! returns the segment to the left of the i'th segment */
  75. __forceinline bool segmentLeftExists(size_t i) const {
  76. assert (flags);
  77. return (flags[i] & RTC_CURVE_FLAG_NEIGHBOR_LEFT) != 0;
  78. }
  79. /*! returns the segment to the right of the i'th segment */
  80. __forceinline bool segmentRightExists(size_t i) const {
  81. assert (flags);
  82. return (flags[i] & RTC_CURVE_FLAG_NEIGHBOR_RIGHT) != 0;
  83. }
  84. /*! returns i'th vertex of the first time step */
  85. __forceinline Vec3ff vertex(size_t i) const {
  86. return vertices0[i];
  87. }
  88. /*! returns i'th vertex of the first time step */
  89. __forceinline const char* vertexPtr(size_t i) const {
  90. return vertices0.getPtr(i);
  91. }
  92. /*! returns i'th normal of the first time step */
  93. __forceinline Vec3fa normal(size_t i) const {
  94. return normals0[i];
  95. }
  96. /*! returns i'th radius of the first time step */
  97. __forceinline float radius(size_t i) const {
  98. return vertices0[i].w;
  99. }
  100. /*! returns i'th vertex of itime'th timestep */
  101. __forceinline Vec3ff vertex(size_t i, size_t itime) const {
  102. return vertices[itime][i];
  103. }
  104. /*! returns i'th vertex of itime'th timestep */
  105. __forceinline const char* vertexPtr(size_t i, size_t itime) const {
  106. return vertices[itime].getPtr(i);
  107. }
  108. /*! returns i'th normal of itime'th timestep */
  109. __forceinline Vec3fa normal(size_t i, size_t itime) const {
  110. return normals[itime][i];
  111. }
  112. /*! returns i'th radius of itime'th timestep */
  113. __forceinline float radius(size_t i, size_t itime) const {
  114. return vertices[itime][i].w;
  115. }
  116. /*! calculates bounding box of i'th line segment */
  117. __forceinline BBox3fa bounds(const Vec3ff& v0, const Vec3ff& v1) const
  118. {
  119. const BBox3ff b = merge(BBox3ff(v0),BBox3ff(v1));
  120. return enlarge((BBox3fa)b,maxRadiusScale*Vec3fa(max(v0.w,v1.w)));
  121. }
  122. /*! calculates bounding box of i'th line segment */
  123. __forceinline BBox3fa bounds(size_t i) const
  124. {
  125. const unsigned int index = segment(i);
  126. const Vec3ff v0 = vertex(index+0);
  127. const Vec3ff v1 = vertex(index+1);
  128. return bounds(v0,v1);
  129. }
  130. /*! calculates bounding box of i'th line segment for the itime'th time step */
  131. __forceinline BBox3fa bounds(size_t i, size_t itime) const
  132. {
  133. const unsigned int index = segment(i);
  134. const Vec3ff v0 = vertex(index+0,itime);
  135. const Vec3ff v1 = vertex(index+1,itime);
  136. return bounds(v0,v1);
  137. }
  138. /*! calculates bounding box of i'th line segment */
  139. __forceinline BBox3fa bounds(const LinearSpace3fa& space, size_t i) const
  140. {
  141. const unsigned int index = segment(i);
  142. const Vec3ff v0 = vertex(index+0);
  143. const Vec3ff v1 = vertex(index+1);
  144. const Vec3ff w0(xfmVector(space,(Vec3fa)v0),v0.w);
  145. const Vec3ff w1(xfmVector(space,(Vec3fa)v1),v1.w);
  146. return bounds(w0,w1);
  147. }
  148. /*! calculates bounding box of i'th line segment for the itime'th time step */
  149. __forceinline BBox3fa bounds(const LinearSpace3fa& space, size_t i, size_t itime) const
  150. {
  151. const unsigned int index = segment(i);
  152. const Vec3ff v0 = vertex(index+0,itime);
  153. const Vec3ff v1 = vertex(index+1,itime);
  154. const Vec3ff w0(xfmVector(space,(Vec3fa)v0),v0.w);
  155. const Vec3ff w1(xfmVector(space,(Vec3fa)v1),v1.w);
  156. return bounds(w0,w1);
  157. }
  158. /*! check if the i'th primitive is valid at the itime'th timestep */
  159. __forceinline bool valid(size_t i, size_t itime) const {
  160. return valid(i, make_range(itime, itime));
  161. }
  162. /*! check if the i'th primitive is valid between the specified time range */
  163. __forceinline bool valid(size_t i, const range<size_t>& itime_range) const
  164. {
  165. const unsigned int index = segment(i);
  166. if (index+1 >= numVertices()) return false;
  167. for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
  168. {
  169. const Vec3ff v0 = vertex(index+0,itime); if (unlikely(!isvalid4(v0))) return false;
  170. const Vec3ff v1 = vertex(index+1,itime); if (unlikely(!isvalid4(v1))) return false;
  171. if (min(v0.w,v1.w) < 0.0f) return false;
  172. }
  173. return true;
  174. }
  175. /*! calculates the linear bounds of the i'th primitive at the itimeGlobal'th time segment */
  176. __forceinline LBBox3fa linearBounds(size_t i, size_t itime) const {
  177. return LBBox3fa(bounds(i,itime+0),bounds(i,itime+1));
  178. }
  179. /*! calculates the build bounds of the i'th primitive, if it's valid */
  180. __forceinline bool buildBounds(size_t i, BBox3fa* bbox) const
  181. {
  182. if (!valid(i,0)) return false;
  183. *bbox = bounds(i);
  184. return true;
  185. }
  186. /*! calculates the build bounds of the i'th primitive at the itime'th time segment, if it's valid */
  187. __forceinline bool buildBounds(size_t i, size_t itime, BBox3fa& bbox) const
  188. {
  189. if (!valid(i,itime+0) || !valid(i,itime+1)) return false;
  190. bbox = bounds(i,itime); // use bounds of first time step in builder
  191. return true;
  192. }
  193. /*! calculates the linear bounds of the i'th primitive for the specified time range */
  194. __forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& dt) const {
  195. return LBBox3fa([&] (size_t itime) { return bounds(primID, itime); }, dt, time_range, fnumTimeSegments);
  196. }
  197. /*! calculates the linear bounds of the i'th primitive for the specified time range */
  198. __forceinline LBBox3fa linearBounds(const LinearSpace3fa& space, size_t primID, const BBox1f& dt) const {
  199. return LBBox3fa([&] (size_t itime) { return bounds(space, primID, itime); }, dt, time_range, fnumTimeSegments);
  200. }
  201. /*! calculates the linear bounds of the i'th primitive for the specified time range */
  202. __forceinline bool linearBounds(size_t i, const BBox1f& time_range, LBBox3fa& bbox) const
  203. {
  204. if (!valid(i, timeSegmentRange(time_range))) return false;
  205. bbox = linearBounds(i, time_range);
  206. return true;
  207. }
  208. /*! get fast access to first vertex buffer */
  209. __forceinline float * getCompactVertexArray () const {
  210. return (float*) vertices0.getPtr();
  211. }
  212. public:
  213. BufferView<unsigned int> segments; //!< array of line segment indices
  214. BufferView<Vec3ff> vertices0; //!< fast access to first vertex buffer
  215. BufferView<Vec3fa> normals0; //!< fast access to first normal buffer
  216. BufferView<char> flags; //!< start, end flag per segment
  217. vector<BufferView<Vec3ff>> vertices; //!< vertex array for each timestep
  218. vector<BufferView<Vec3fa>> normals; //!< normal array for each timestep
  219. vector<BufferView<char>> vertexAttribs; //!< user buffers
  220. int tessellationRate; //!< tessellation rate for bezier curve
  221. float maxRadiusScale = 1.0; //!< maximal min-width scaling of curve radii
  222. };
  223. namespace isa
  224. {
  225. struct LineSegmentsISA : public LineSegments
  226. {
  227. LineSegmentsISA (Device* device, Geometry::GType gtype)
  228. : LineSegments(device,gtype) {}
  229. Vec3fa computeDirection(unsigned int primID) const
  230. {
  231. const unsigned vtxID = segment(primID);
  232. const Vec3fa v0 = vertex(vtxID+0);
  233. const Vec3fa v1 = vertex(vtxID+1);
  234. return v1-v0;
  235. }
  236. Vec3fa computeDirection(unsigned int primID, size_t time) const
  237. {
  238. const unsigned vtxID = segment(primID);
  239. const Vec3fa v0 = vertex(vtxID+0,time);
  240. const Vec3fa v1 = vertex(vtxID+1,time);
  241. return v1-v0;
  242. }
  243. PrimInfo createPrimRefArray(mvector<PrimRef>& prims, const range<size_t>& r, size_t k, unsigned int geomID) const
  244. {
  245. PrimInfo pinfo(empty);
  246. for (size_t j=r.begin(); j<r.end(); j++)
  247. {
  248. BBox3fa bounds = empty;
  249. if (!buildBounds(j,&bounds)) continue;
  250. const PrimRef prim(bounds,geomID,unsigned(j));
  251. pinfo.add_center2(prim);
  252. prims[k++] = prim;
  253. }
  254. return pinfo;
  255. }
  256. PrimInfo createPrimRefArrayMB(mvector<PrimRef>& prims, size_t itime, const range<size_t>& r, size_t k, unsigned int geomID) const
  257. {
  258. PrimInfo pinfo(empty);
  259. for (size_t j=r.begin(); j<r.end(); j++)
  260. {
  261. BBox3fa bounds = empty;
  262. if (!buildBounds(j,itime,bounds)) continue;
  263. const PrimRef prim(bounds,geomID,unsigned(j));
  264. pinfo.add_center2(prim);
  265. prims[k++] = prim;
  266. }
  267. return pinfo;
  268. }
  269. PrimInfoMB createPrimRefMBArray(mvector<PrimRefMB>& prims, const BBox1f& t0t1, const range<size_t>& r, size_t k, unsigned int geomID) const
  270. {
  271. PrimInfoMB pinfo(empty);
  272. for (size_t j=r.begin(); j<r.end(); j++)
  273. {
  274. if (!valid(j, timeSegmentRange(t0t1))) continue;
  275. const PrimRefMB prim(linearBounds(j,t0t1),this->numTimeSegments(),this->time_range,this->numTimeSegments(),geomID,unsigned(j));
  276. pinfo.add_primref(prim);
  277. prims[k++] = prim;
  278. }
  279. return pinfo;
  280. }
  281. BBox3fa vbounds(size_t i) const {
  282. return bounds(i);
  283. }
  284. BBox3fa vbounds(const LinearSpace3fa& space, size_t i) const {
  285. return bounds(space,i);
  286. }
  287. LBBox3fa vlinearBounds(size_t primID, const BBox1f& time_range) const {
  288. return linearBounds(primID,time_range);
  289. }
  290. LBBox3fa vlinearBounds(const LinearSpace3fa& space, size_t primID, const BBox1f& time_range) const {
  291. return linearBounds(space,primID,time_range);
  292. }
  293. };
  294. }
  295. DECLARE_ISA_FUNCTION(LineSegments*, createLineSegments, Device* COMMA Geometry::GType);
  296. }