scene_curves.h 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764
  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. #include "../subdiv/bezier_curve.h"
  8. #include "../subdiv/hermite_curve.h"
  9. #include "../subdiv/bspline_curve.h"
  10. #include "../subdiv/catmullrom_curve.h"
  11. #include "../subdiv/linear_bezier_patch.h"
  12. namespace embree
  13. {
  14. /*! represents an array of bicubic bezier curves */
  15. struct CurveGeometry : public Geometry
  16. {
  17. /*! type of this geometry */
  18. static const Geometry::GTypeMask geom_type = Geometry::MTY_CURVE4;
  19. public:
  20. /*! bezier curve construction */
  21. CurveGeometry (Device* device, Geometry::GType gtype);
  22. public:
  23. void setMask(unsigned mask);
  24. void setNumTimeSteps (unsigned int numTimeSteps);
  25. void setVertexAttributeCount (unsigned int N);
  26. void setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num);
  27. void* getBuffer(RTCBufferType type, unsigned int slot);
  28. void updateBuffer(RTCBufferType type, unsigned int slot);
  29. void commit();
  30. bool verify();
  31. void setTessellationRate(float N);
  32. void setMaxRadiusScale(float s);
  33. void addElementsToCount (GeometryCounts & counts) const;
  34. public:
  35. /*! returns the number of vertices */
  36. __forceinline size_t numVertices() const {
  37. return vertices[0].size();
  38. }
  39. /*! returns the i'th curve */
  40. __forceinline const unsigned int& curve(size_t i) const {
  41. return curves[i];
  42. }
  43. /*! returns i'th vertex of the first time step */
  44. __forceinline Vec3ff vertex(size_t i) const {
  45. return vertices0[i];
  46. }
  47. /*! returns i'th normal of the first time step */
  48. __forceinline Vec3fa normal(size_t i) const {
  49. return normals0[i];
  50. }
  51. /*! returns i'th tangent of the first time step */
  52. __forceinline Vec3ff tangent(size_t i) const {
  53. return tangents0[i];
  54. }
  55. /*! returns i'th normal derivative of the first time step */
  56. __forceinline Vec3fa dnormal(size_t i) const {
  57. return dnormals0[i];
  58. }
  59. /*! returns i'th radius of the first time step */
  60. __forceinline float radius(size_t i) const {
  61. return vertices0[i].w;
  62. }
  63. /*! returns i'th vertex of itime'th timestep */
  64. __forceinline Vec3ff vertex(size_t i, size_t itime) const {
  65. return vertices[itime][i];
  66. }
  67. /*! returns i'th normal of itime'th timestep */
  68. __forceinline Vec3fa normal(size_t i, size_t itime) const {
  69. return normals[itime][i];
  70. }
  71. /*! returns i'th tangent of itime'th timestep */
  72. __forceinline Vec3ff tangent(size_t i, size_t itime) const {
  73. return tangents[itime][i];
  74. }
  75. /*! returns i'th normal derivative of itime'th timestep */
  76. __forceinline Vec3fa dnormal(size_t i, size_t itime) const {
  77. return dnormals[itime][i];
  78. }
  79. /*! returns i'th radius of itime'th timestep */
  80. __forceinline float radius(size_t i, size_t itime) const {
  81. return vertices[itime][i].w;
  82. }
  83. /*! gathers the curve starting with i'th vertex */
  84. __forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, size_t i) const
  85. {
  86. p0 = vertex(i+0);
  87. p1 = vertex(i+1);
  88. p2 = vertex(i+2);
  89. p3 = vertex(i+3);
  90. }
  91. /*! gathers the curve starting with i'th vertex of itime'th timestep */
  92. __forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, size_t i, size_t itime) const
  93. {
  94. p0 = vertex(i+0,itime);
  95. p1 = vertex(i+1,itime);
  96. p2 = vertex(i+2,itime);
  97. p3 = vertex(i+3,itime);
  98. }
  99. /*! gathers the curve normals starting with i'th vertex */
  100. __forceinline void gather_normals(Vec3fa& n0, Vec3fa& n1, Vec3fa& n2, Vec3fa& n3, size_t i) const
  101. {
  102. n0 = normal(i+0);
  103. n1 = normal(i+1);
  104. n2 = normal(i+2);
  105. n3 = normal(i+3);
  106. }
  107. /*! gathers the curve starting with i'th vertex */
  108. __forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, Vec3fa& n0, Vec3fa& n1, Vec3fa& n2, Vec3fa& n3, size_t i) const
  109. {
  110. p0 = vertex(i+0);
  111. p1 = vertex(i+1);
  112. p2 = vertex(i+2);
  113. p3 = vertex(i+3);
  114. n0 = normal(i+0);
  115. n1 = normal(i+1);
  116. n2 = normal(i+2);
  117. n3 = normal(i+3);
  118. }
  119. /*! gathers the curve starting with i'th vertex of itime'th timestep */
  120. __forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, Vec3fa& n0, Vec3fa& n1, Vec3fa& n2, Vec3fa& n3, size_t i, size_t itime) const
  121. {
  122. p0 = vertex(i+0,itime);
  123. p1 = vertex(i+1,itime);
  124. p2 = vertex(i+2,itime);
  125. p3 = vertex(i+3,itime);
  126. n0 = normal(i+0,itime);
  127. n1 = normal(i+1,itime);
  128. n2 = normal(i+2,itime);
  129. n3 = normal(i+3,itime);
  130. }
  131. /*! prefetches the curve starting with i'th vertex of itime'th timestep */
  132. __forceinline void prefetchL1_vertices(size_t i) const
  133. {
  134. prefetchL1(vertices0.getPtr(i)+0);
  135. prefetchL1(vertices0.getPtr(i)+64);
  136. }
  137. /*! prefetches the curve starting with i'th vertex of itime'th timestep */
  138. __forceinline void prefetchL2_vertices(size_t i) const
  139. {
  140. prefetchL2(vertices0.getPtr(i)+0);
  141. prefetchL2(vertices0.getPtr(i)+64);
  142. }
  143. /*! loads curve vertices for specified time */
  144. __forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, size_t i, float time) const
  145. {
  146. float ftime;
  147. const size_t itime = timeSegment(time, ftime);
  148. const float t0 = 1.0f - ftime;
  149. const float t1 = ftime;
  150. Vec3ff a0,a1,a2,a3;
  151. gather(a0,a1,a2,a3,i,itime);
  152. Vec3ff b0,b1,b2,b3;
  153. gather(b0,b1,b2,b3,i,itime+1);
  154. p0 = madd(Vec3ff(t0),a0,t1*b0);
  155. p1 = madd(Vec3ff(t0),a1,t1*b1);
  156. p2 = madd(Vec3ff(t0),a2,t1*b2);
  157. p3 = madd(Vec3ff(t0),a3,t1*b3);
  158. }
  159. /*! loads curve vertices for specified time */
  160. __forceinline void gather_safe(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, size_t i, float time) const
  161. {
  162. if (hasMotionBlur()) gather(p0,p1,p2,p3,i,time);
  163. else gather(p0,p1,p2,p3,i);
  164. }
  165. /*! loads curve vertices for specified time */
  166. __forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, Vec3fa& n0, Vec3fa& n1, Vec3fa& n2, Vec3fa& n3, size_t i, float time) const
  167. {
  168. float ftime;
  169. const size_t itime = timeSegment(time, ftime);
  170. const float t0 = 1.0f - ftime;
  171. const float t1 = ftime;
  172. Vec3ff a0,a1,a2,a3; Vec3fa an0,an1,an2,an3;
  173. gather(a0,a1,a2,a3,an0,an1,an2,an3,i,itime);
  174. Vec3ff b0,b1,b2,b3; Vec3fa bn0,bn1,bn2,bn3;
  175. gather(b0,b1,b2,b3,bn0,bn1,bn2,bn3,i,itime+1);
  176. p0 = madd(Vec3ff(t0),a0,t1*b0);
  177. p1 = madd(Vec3ff(t0),a1,t1*b1);
  178. p2 = madd(Vec3ff(t0),a2,t1*b2);
  179. p3 = madd(Vec3ff(t0),a3,t1*b3);
  180. n0 = madd(Vec3ff(t0),an0,t1*bn0);
  181. n1 = madd(Vec3ff(t0),an1,t1*bn1);
  182. n2 = madd(Vec3ff(t0),an2,t1*bn2);
  183. n3 = madd(Vec3ff(t0),an3,t1*bn3);
  184. }
  185. /*! loads curve vertices for specified time for mblur and non-mblur case */
  186. __forceinline void gather_safe(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, Vec3fa& n0, Vec3fa& n1, Vec3fa& n2, Vec3fa& n3, size_t i, float time) const
  187. {
  188. if (hasMotionBlur()) gather(p0,p1,p2,p3,n0,n1,n2,n3,i,time);
  189. else gather(p0,p1,p2,p3,n0,n1,n2,n3,i);
  190. }
  191. template<typename SourceCurve3ff, typename SourceCurve3fa, typename TensorLinearCubicBezierSurface3fa>
  192. __forceinline TensorLinearCubicBezierSurface3fa getNormalOrientedCurve(RayQueryContext* context, const Vec3fa& ray_org, const unsigned int primID, const size_t itime) const
  193. {
  194. Vec3ff v0,v1,v2,v3; Vec3fa n0,n1,n2,n3;
  195. unsigned int vertexID = curve(primID);
  196. gather(v0,v1,v2,v3,n0,n1,n2,n3,vertexID,itime);
  197. SourceCurve3ff ccurve(v0,v1,v2,v3);
  198. SourceCurve3fa ncurve(n0,n1,n2,n3);
  199. ccurve = enlargeRadiusToMinWidth(context,this,ray_org,ccurve);
  200. return TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(ccurve,ncurve);
  201. }
  202. template<typename SourceCurve3ff, typename SourceCurve3fa, typename TensorLinearCubicBezierSurface3fa>
  203. __forceinline TensorLinearCubicBezierSurface3fa getNormalOrientedCurve(RayQueryContext* context, const Vec3fa& ray_org, const unsigned int primID, const float time) const
  204. {
  205. float ftime;
  206. const size_t itime = timeSegment(time, ftime);
  207. const TensorLinearCubicBezierSurface3fa curve0 = getNormalOrientedCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context,ray_org,primID,itime+0);
  208. const TensorLinearCubicBezierSurface3fa curve1 = getNormalOrientedCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context,ray_org,primID,itime+1);
  209. return clerp(curve0,curve1,ftime);
  210. }
  211. template<typename SourceCurve3ff, typename SourceCurve3fa, typename TensorLinearCubicBezierSurface3fa>
  212. __forceinline TensorLinearCubicBezierSurface3fa getNormalOrientedCurveSafe(RayQueryContext* context, const Vec3fa& ray_org, const unsigned int primID, const float time) const
  213. {
  214. float ftime = 0.0f;
  215. const size_t itime = hasMotionBlur() ? timeSegment(time, ftime) : 0;
  216. const TensorLinearCubicBezierSurface3fa curve0 = getNormalOrientedCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context,ray_org,primID,itime+0);
  217. if (hasMotionBlur()) {
  218. const TensorLinearCubicBezierSurface3fa curve1 = getNormalOrientedCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context,ray_org,primID,itime+1);
  219. return clerp(curve0,curve1,ftime);
  220. }
  221. return curve0;
  222. }
  223. /*! gathers the hermite curve starting with i'th vertex */
  224. __forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3ff& p1, Vec3ff& t1, size_t i) const
  225. {
  226. p0 = vertex (i+0);
  227. p1 = vertex (i+1);
  228. t0 = tangent(i+0);
  229. t1 = tangent(i+1);
  230. }
  231. /*! gathers the hermite curve starting with i'th vertex of itime'th timestep */
  232. __forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3ff& p1, Vec3ff& t1, size_t i, size_t itime) const
  233. {
  234. p0 = vertex (i+0,itime);
  235. p1 = vertex (i+1,itime);
  236. t0 = tangent(i+0,itime);
  237. t1 = tangent(i+1,itime);
  238. }
  239. /*! loads curve vertices for specified time */
  240. __forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3ff& p1, Vec3ff& t1, size_t i, float time) const
  241. {
  242. float ftime;
  243. const size_t itime = timeSegment(time, ftime);
  244. const float f0 = 1.0f - ftime, f1 = ftime;
  245. Vec3ff ap0,at0,ap1,at1;
  246. gather_hermite(ap0,at0,ap1,at1,i,itime);
  247. Vec3ff bp0,bt0,bp1,bt1;
  248. gather_hermite(bp0,bt0,bp1,bt1,i,itime+1);
  249. p0 = madd(Vec3ff(f0),ap0,f1*bp0);
  250. t0 = madd(Vec3ff(f0),at0,f1*bt0);
  251. p1 = madd(Vec3ff(f0),ap1,f1*bp1);
  252. t1 = madd(Vec3ff(f0),at1,f1*bt1);
  253. }
  254. /*! loads curve vertices for specified time for mblur and non-mblur geometry */
  255. __forceinline void gather_hermite_safe(Vec3ff& p0, Vec3ff& t0, Vec3ff& p1, Vec3ff& t1, size_t i, float time) const
  256. {
  257. if (hasMotionBlur()) gather_hermite(p0,t0,p1,t1,i,time);
  258. else gather_hermite(p0,t0,p1,t1,i);
  259. }
  260. /*! gathers the hermite curve starting with i'th vertex */
  261. __forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3fa& n0, Vec3fa& dn0, Vec3ff& p1, Vec3ff& t1, Vec3fa& n1, Vec3fa& dn1, size_t i) const
  262. {
  263. p0 = vertex (i+0);
  264. p1 = vertex (i+1);
  265. t0 = tangent(i+0);
  266. t1 = tangent(i+1);
  267. n0 = normal(i+0);
  268. n1 = normal(i+1);
  269. dn0 = dnormal(i+0);
  270. dn1 = dnormal(i+1);
  271. }
  272. /*! gathers the hermite curve starting with i'th vertex of itime'th timestep */
  273. __forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3fa& n0, Vec3fa& dn0, Vec3ff& p1, Vec3ff& t1, Vec3fa& n1, Vec3fa& dn1, size_t i, size_t itime) const
  274. {
  275. p0 = vertex (i+0,itime);
  276. p1 = vertex (i+1,itime);
  277. t0 = tangent(i+0,itime);
  278. t1 = tangent(i+1,itime);
  279. n0 = normal(i+0,itime);
  280. n1 = normal(i+1,itime);
  281. dn0 = dnormal(i+0,itime);
  282. dn1 = dnormal(i+1,itime);
  283. }
  284. /*! loads curve vertices for specified time */
  285. __forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3fa& n0, Vec3fa& dn0, Vec3ff& p1, Vec3ff& t1, Vec3fa& n1, Vec3fa& dn1, size_t i, float time) const
  286. {
  287. float ftime;
  288. const size_t itime = timeSegment(time, ftime);
  289. const float f0 = 1.0f - ftime, f1 = ftime;
  290. Vec3ff ap0,at0,ap1,at1; Vec3fa an0,adn0,an1,adn1;
  291. gather_hermite(ap0,at0,an0,adn0,ap1,at1,an1,adn1,i,itime);
  292. Vec3ff bp0,bt0,bp1,bt1; Vec3fa bn0,bdn0,bn1,bdn1;
  293. gather_hermite(bp0,bt0,bn0,bdn0,bp1,bt1,bn1,bdn1,i,itime+1);
  294. p0 = madd(Vec3ff(f0),ap0,f1*bp0);
  295. t0 = madd(Vec3ff(f0),at0,f1*bt0);
  296. n0 = madd(Vec3ff(f0),an0,f1*bn0);
  297. dn0= madd(Vec3ff(f0),adn0,f1*bdn0);
  298. p1 = madd(Vec3ff(f0),ap1,f1*bp1);
  299. t1 = madd(Vec3ff(f0),at1,f1*bt1);
  300. n1 = madd(Vec3ff(f0),an1,f1*bn1);
  301. dn1= madd(Vec3ff(f0),adn1,f1*bdn1);
  302. }
  303. /*! loads curve vertices for specified time */
  304. __forceinline void gather_hermite_safe(Vec3ff& p0, Vec3ff& t0, Vec3fa& n0, Vec3fa& dn0, Vec3ff& p1, Vec3ff& t1, Vec3fa& n1, Vec3fa& dn1, size_t i, float time) const
  305. {
  306. if (hasMotionBlur()) gather_hermite(p0,t0,n0,dn0,p1,t1,n1,dn1,i,time);
  307. else gather_hermite(p0,t0,n0,dn0,p1,t1,n1,dn1,i);
  308. }
  309. template<typename SourceCurve3ff, typename SourceCurve3fa, typename TensorLinearCubicBezierSurface3fa>
  310. __forceinline TensorLinearCubicBezierSurface3fa getNormalOrientedHermiteCurve(RayQueryContext* context, const Vec3fa& ray_org, const unsigned int primID, const size_t itime) const
  311. {
  312. Vec3ff v0,t0,v1,t1; Vec3fa n0,dn0,n1,dn1;
  313. unsigned int vertexID = curve(primID);
  314. gather_hermite(v0,t0,n0,dn0,v1,t1,n1,dn1,vertexID,itime);
  315. SourceCurve3ff ccurve(v0,t0,v1,t1);
  316. SourceCurve3fa ncurve(n0,dn0,n1,dn1);
  317. ccurve = enlargeRadiusToMinWidth(context,this,ray_org,ccurve);
  318. return TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(ccurve,ncurve);
  319. }
  320. template<typename SourceCurve3ff, typename SourceCurve3fa, typename TensorLinearCubicBezierSurface3fa>
  321. __forceinline TensorLinearCubicBezierSurface3fa getNormalOrientedHermiteCurve(RayQueryContext* context, const Vec3fa& ray_org, const unsigned int primID, const float time) const
  322. {
  323. float ftime;
  324. const size_t itime = timeSegment(time, ftime);
  325. const TensorLinearCubicBezierSurface3fa curve0 = getNormalOrientedHermiteCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,itime+0);
  326. const TensorLinearCubicBezierSurface3fa curve1 = getNormalOrientedHermiteCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,itime+1);
  327. return clerp(curve0,curve1,ftime);
  328. }
  329. template<typename SourceCurve3ff, typename SourceCurve3fa, typename TensorLinearCubicBezierSurface3fa>
  330. __forceinline TensorLinearCubicBezierSurface3fa getNormalOrientedHermiteCurveSafe(RayQueryContext* context, const Vec3fa& ray_org, const unsigned int primID, const float time) const
  331. {
  332. float ftime = 0.0f;
  333. const size_t itime = hasMotionBlur() ? timeSegment(time, ftime) : 0;
  334. const TensorLinearCubicBezierSurface3fa curve0 = getNormalOrientedHermiteCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,itime+0);
  335. if (hasMotionBlur()) {
  336. const TensorLinearCubicBezierSurface3fa curve1 = getNormalOrientedHermiteCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,itime+1);
  337. return clerp(curve0,curve1,ftime);
  338. }
  339. return curve0;
  340. }
  341. /* returns the projected area */
  342. __forceinline float projectedPrimitiveArea(const size_t i) const {
  343. return 1.0f;
  344. }
  345. private:
  346. void resizeBuffers(unsigned int numSteps);
  347. public:
  348. BufferView<unsigned int> curves; //!< array of curve indices
  349. BufferView<Vec3ff> vertices0; //!< fast access to first vertex buffer
  350. BufferView<Vec3fa> normals0; //!< fast access to first normal buffer
  351. BufferView<Vec3ff> tangents0; //!< fast access to first tangent buffer
  352. BufferView<Vec3fa> dnormals0; //!< fast access to first normal derivative buffer
  353. Device::vector<BufferView<Vec3ff>> vertices = device; //!< vertex array for each timestep
  354. Device::vector<BufferView<Vec3fa>> normals = device; //!< normal array for each timestep
  355. Device::vector<BufferView<Vec3ff>> tangents = device; //!< tangent array for each timestep
  356. Device::vector<BufferView<Vec3fa>> dnormals = device; //!< normal derivative array for each timestep
  357. BufferView<char> flags; //!< start, end flag per segment
  358. Device::vector<BufferView<char>> vertexAttribs = device; //!< user buffers
  359. int tessellationRate; //!< tessellation rate for flat curve
  360. float maxRadiusScale = 1.0; //!< maximal min-width scaling of curve radii
  361. };
  362. namespace isa
  363. {
  364. template<template<typename Ty> class Curve>
  365. struct CurveGeometryInterface : public CurveGeometry
  366. {
  367. typedef Curve<Vec3ff> Curve3ff;
  368. typedef Curve<Vec3fa> Curve3fa;
  369. CurveGeometryInterface (Device* device, Geometry::GType gtype)
  370. : CurveGeometry(device,gtype) {}
  371. __forceinline const Curve3ff getCurveScaledRadius(size_t i, size_t itime = 0) const
  372. {
  373. const unsigned int index = curve(i);
  374. Vec3ff v0 = vertex(index+0,itime);
  375. Vec3ff v1 = vertex(index+1,itime);
  376. Vec3ff v2 = vertex(index+2,itime);
  377. Vec3ff v3 = vertex(index+3,itime);
  378. v0.w *= maxRadiusScale;
  379. v1.w *= maxRadiusScale;
  380. v2.w *= maxRadiusScale;
  381. v3.w *= maxRadiusScale;
  382. return Curve3ff (v0,v1,v2,v3);
  383. }
  384. __forceinline const Curve3ff getCurveScaledRadius(const LinearSpace3fa& space, size_t i, size_t itime = 0) const
  385. {
  386. const unsigned int index = curve(i);
  387. const Vec3ff v0 = vertex(index+0,itime);
  388. const Vec3ff v1 = vertex(index+1,itime);
  389. const Vec3ff v2 = vertex(index+2,itime);
  390. const Vec3ff v3 = vertex(index+3,itime);
  391. const Vec3ff w0(xfmPoint(space,(Vec3fa)v0), maxRadiusScale*v0.w);
  392. const Vec3ff w1(xfmPoint(space,(Vec3fa)v1), maxRadiusScale*v1.w);
  393. const Vec3ff w2(xfmPoint(space,(Vec3fa)v2), maxRadiusScale*v2.w);
  394. const Vec3ff w3(xfmPoint(space,(Vec3fa)v3), maxRadiusScale*v3.w);
  395. return Curve3ff(w0,w1,w2,w3);
  396. }
  397. __forceinline const Curve3ff getCurveScaledRadius(const Vec3fa& ofs, const float scale, const float r_scale0, const LinearSpace3fa& space, size_t i, size_t itime = 0) const
  398. {
  399. const float r_scale = r_scale0*scale;
  400. const unsigned int index = curve(i);
  401. const Vec3ff v0 = vertex(index+0,itime);
  402. const Vec3ff v1 = vertex(index+1,itime);
  403. const Vec3ff v2 = vertex(index+2,itime);
  404. const Vec3ff v3 = vertex(index+3,itime);
  405. const Vec3ff w0(xfmPoint(space,((Vec3fa)v0-ofs)*Vec3fa(scale)), maxRadiusScale*v0.w*r_scale);
  406. const Vec3ff w1(xfmPoint(space,((Vec3fa)v1-ofs)*Vec3fa(scale)), maxRadiusScale*v1.w*r_scale);
  407. const Vec3ff w2(xfmPoint(space,((Vec3fa)v2-ofs)*Vec3fa(scale)), maxRadiusScale*v2.w*r_scale);
  408. const Vec3ff w3(xfmPoint(space,((Vec3fa)v3-ofs)*Vec3fa(scale)), maxRadiusScale*v3.w*r_scale);
  409. return Curve3ff(w0,w1,w2,w3);
  410. }
  411. __forceinline const Curve3fa getNormalCurve(size_t i, size_t itime = 0) const
  412. {
  413. const unsigned int index = curve(i);
  414. const Vec3fa n0 = normal(index+0,itime);
  415. const Vec3fa n1 = normal(index+1,itime);
  416. const Vec3fa n2 = normal(index+2,itime);
  417. const Vec3fa n3 = normal(index+3,itime);
  418. return Curve3fa (n0,n1,n2,n3);
  419. }
  420. __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(size_t i, size_t itime = 0) const
  421. {
  422. const Curve3ff center = getCurveScaledRadius(i,itime);
  423. const Curve3fa normal = getNormalCurve(i,itime);
  424. const TensorLinearCubicBezierSurface3fa ocurve = TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(center,normal);
  425. return ocurve;
  426. }
  427. __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(const LinearSpace3fa& space, size_t i, size_t itime = 0) const {
  428. return getOrientedCurveScaledRadius(i,itime).xfm(space);
  429. }
  430. __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(const Vec3fa& ofs, const float scale, const LinearSpace3fa& space, size_t i, size_t itime = 0) const {
  431. return getOrientedCurveScaledRadius(i,itime).xfm(space,ofs,scale);
  432. }
  433. /*! check if the i'th primitive is valid at the itime'th time step */
  434. __forceinline bool valid(Geometry::GType ctype, size_t i, const range<size_t>& itime_range) const
  435. {
  436. const unsigned int index = curve(i);
  437. if (index+3 >= numVertices()) return false;
  438. for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
  439. {
  440. const float r0 = radius(index+0,itime);
  441. const float r1 = radius(index+1,itime);
  442. const float r2 = radius(index+2,itime);
  443. const float r3 = radius(index+3,itime);
  444. if (!isvalid(r0) || !isvalid(r1) || !isvalid(r2) || !isvalid(r3))
  445. return false;
  446. const Vec3fa v0 = vertex(index+0,itime);
  447. const Vec3fa v1 = vertex(index+1,itime);
  448. const Vec3fa v2 = vertex(index+2,itime);
  449. const Vec3fa v3 = vertex(index+3,itime);
  450. if (!isvalid(v0) || !isvalid(v1) || !isvalid(v2) || !isvalid(v3))
  451. return false;
  452. if (ctype == Geometry::GTY_SUBTYPE_ORIENTED_CURVE)
  453. {
  454. const Vec3fa n0 = normal(index+0,itime);
  455. const Vec3fa n1 = normal(index+1,itime);
  456. if (!isvalid(n0) || !isvalid(n1))
  457. return false;
  458. const BBox3fa b = getOrientedCurveScaledRadius(i,itime).accurateBounds();
  459. if (!isvalid(b))
  460. return false;
  461. }
  462. }
  463. return true;
  464. }
  465. template<int N>
  466. void interpolate_impl(const RTCInterpolateArguments* const args)
  467. {
  468. unsigned int primID = args->primID;
  469. float u = args->u;
  470. RTCBufferType bufferType = args->bufferType;
  471. unsigned int bufferSlot = args->bufferSlot;
  472. float* P = args->P;
  473. float* dPdu = args->dPdu;
  474. float* ddPdudu = args->ddPdudu;
  475. unsigned int valueCount = args->valueCount;
  476. /* calculate base pointer and stride */
  477. assert((bufferType == RTC_BUFFER_TYPE_VERTEX && bufferSlot < numTimeSteps) ||
  478. (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE && bufferSlot <= vertexAttribs.size()));
  479. const char* src = nullptr;
  480. size_t stride = 0;
  481. if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE) {
  482. src = vertexAttribs[bufferSlot].getPtr();
  483. stride = vertexAttribs[bufferSlot].getStride();
  484. } else {
  485. src = vertices[bufferSlot].getPtr();
  486. stride = vertices[bufferSlot].getStride();
  487. }
  488. for (unsigned int i=0; i<valueCount; i+=N)
  489. {
  490. size_t ofs = i*sizeof(float);
  491. const size_t index = curves[primID];
  492. const vbool<N> valid = vint<N>((int)i)+vint<N>(step) < vint<N>((int)valueCount);
  493. const vfloat<N> p0 = mem<vfloat<N>>::loadu(valid,(float*)&src[(index+0)*stride+ofs]);
  494. const vfloat<N> p1 = mem<vfloat<N>>::loadu(valid,(float*)&src[(index+1)*stride+ofs]);
  495. const vfloat<N> p2 = mem<vfloat<N>>::loadu(valid,(float*)&src[(index+2)*stride+ofs]);
  496. const vfloat<N> p3 = mem<vfloat<N>>::loadu(valid,(float*)&src[(index+3)*stride+ofs]);
  497. const Curve<vfloat<N>> curve(p0,p1,p2,p3);
  498. if (P ) mem<vfloat<N>>::storeu(valid,P+i, curve.eval(u));
  499. if (dPdu ) mem<vfloat<N>>::storeu(valid,dPdu+i, curve.eval_du(u));
  500. if (ddPdudu) mem<vfloat<N>>::storeu(valid,ddPdudu+i,curve.eval_dudu(u));
  501. }
  502. }
  503. void interpolate(const RTCInterpolateArguments* const args) {
  504. interpolate_impl<4>(args);
  505. }
  506. };
  507. template<template<typename Ty> class Curve>
  508. struct HermiteCurveGeometryInterface : public CurveGeometry
  509. {
  510. typedef Curve<Vec3ff> HermiteCurve3ff;
  511. typedef Curve<Vec3fa> HermiteCurve3fa;
  512. HermiteCurveGeometryInterface (Device* device, Geometry::GType gtype)
  513. : CurveGeometry(device,gtype) {}
  514. __forceinline const HermiteCurve3ff getCurveScaledRadius(size_t i, size_t itime = 0) const
  515. {
  516. const unsigned int index = curve(i);
  517. Vec3ff v0 = vertex(index+0,itime);
  518. Vec3ff v1 = vertex(index+1,itime);
  519. Vec3ff t0 = tangent(index+0,itime);
  520. Vec3ff t1 = tangent(index+1,itime);
  521. v0.w *= maxRadiusScale;
  522. v1.w *= maxRadiusScale;
  523. t0.w *= maxRadiusScale;
  524. t1.w *= maxRadiusScale;
  525. return HermiteCurve3ff (v0,t0,v1,t1);
  526. }
  527. __forceinline const HermiteCurve3ff getCurveScaledRadius(const LinearSpace3fa& space, size_t i, size_t itime = 0) const
  528. {
  529. const unsigned int index = curve(i);
  530. const Vec3ff v0 = vertex(index+0,itime);
  531. const Vec3ff v1 = vertex(index+1,itime);
  532. const Vec3ff t0 = tangent(index+0,itime);
  533. const Vec3ff t1 = tangent(index+1,itime);
  534. const Vec3ff V0(xfmPoint(space,(Vec3fa)v0),maxRadiusScale*v0.w);
  535. const Vec3ff V1(xfmPoint(space,(Vec3fa)v1),maxRadiusScale*v1.w);
  536. const Vec3ff T0(xfmVector(space,(Vec3fa)t0),maxRadiusScale*t0.w);
  537. const Vec3ff T1(xfmVector(space,(Vec3fa)t1),maxRadiusScale*t1.w);
  538. return HermiteCurve3ff(V0,T0,V1,T1);
  539. }
  540. __forceinline const HermiteCurve3ff getCurveScaledRadius(const Vec3fa& ofs, const float scale, const float r_scale0, const LinearSpace3fa& space, size_t i, size_t itime = 0) const
  541. {
  542. const float r_scale = r_scale0*scale;
  543. const unsigned int index = curve(i);
  544. const Vec3ff v0 = vertex(index+0,itime);
  545. const Vec3ff v1 = vertex(index+1,itime);
  546. const Vec3ff t0 = tangent(index+0,itime);
  547. const Vec3ff t1 = tangent(index+1,itime);
  548. const Vec3ff V0(xfmPoint(space,(v0-ofs)*Vec3fa(scale)), maxRadiusScale*v0.w*r_scale);
  549. const Vec3ff V1(xfmPoint(space,(v1-ofs)*Vec3fa(scale)), maxRadiusScale*v1.w*r_scale);
  550. const Vec3ff T0(xfmVector(space,t0*Vec3fa(scale)), maxRadiusScale*t0.w*r_scale);
  551. const Vec3ff T1(xfmVector(space,t1*Vec3fa(scale)), maxRadiusScale*t1.w*r_scale);
  552. return HermiteCurve3ff(V0,T0,V1,T1);
  553. }
  554. __forceinline const HermiteCurve3fa getNormalCurve(size_t i, size_t itime = 0) const
  555. {
  556. const unsigned int index = curve(i);
  557. const Vec3fa n0 = normal(index+0,itime);
  558. const Vec3fa n1 = normal(index+1,itime);
  559. const Vec3fa dn0 = dnormal(index+0,itime);
  560. const Vec3fa dn1 = dnormal(index+1,itime);
  561. return HermiteCurve3fa (n0,dn0,n1,dn1);
  562. }
  563. __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(size_t i, size_t itime = 0) const
  564. {
  565. const HermiteCurve3ff center = getCurveScaledRadius(i,itime);
  566. const HermiteCurve3fa normal = getNormalCurve(i,itime);
  567. const TensorLinearCubicBezierSurface3fa ocurve = TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(center,normal);
  568. return ocurve;
  569. }
  570. __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(const LinearSpace3fa& space, size_t i, size_t itime = 0) const {
  571. return getOrientedCurveScaledRadius(i,itime).xfm(space);
  572. }
  573. __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(const Vec3fa& ofs, const float scale, const LinearSpace3fa& space, size_t i, size_t itime = 0) const {
  574. return getOrientedCurveScaledRadius(i,itime).xfm(space,ofs,scale);
  575. }
  576. /*! check if the i'th primitive is valid at the itime'th time step */
  577. __forceinline bool valid(Geometry::GType ctype, size_t i, const range<size_t>& itime_range) const
  578. {
  579. const unsigned int index = curve(i);
  580. if (index+1 >= numVertices()) return false;
  581. for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
  582. {
  583. const Vec3ff v0 = vertex(index+0,itime);
  584. const Vec3ff v1 = vertex(index+1,itime);
  585. if (!isvalid4(v0) || !isvalid4(v1))
  586. return false;
  587. const Vec3ff t0 = tangent(index+0,itime);
  588. const Vec3ff t1 = tangent(index+1,itime);
  589. if (!isvalid4(t0) || !isvalid4(t1))
  590. return false;
  591. if (ctype == Geometry::GTY_SUBTYPE_ORIENTED_CURVE)
  592. {
  593. const Vec3fa n0 = normal(index+0,itime);
  594. const Vec3fa n1 = normal(index+1,itime);
  595. if (!isvalid(n0) || !isvalid(n1))
  596. return false;
  597. const Vec3fa dn0 = dnormal(index+0,itime);
  598. const Vec3fa dn1 = dnormal(index+1,itime);
  599. if (!isvalid(dn0) || !isvalid(dn1))
  600. return false;
  601. const BBox3fa b = getOrientedCurveScaledRadius(i,itime).accurateBounds();
  602. if (!isvalid(b))
  603. return false;
  604. }
  605. }
  606. return true;
  607. }
  608. template<int N>
  609. void interpolate_impl(const RTCInterpolateArguments* const args)
  610. {
  611. unsigned int primID = args->primID;
  612. float u = args->u;
  613. RTCBufferType bufferType = args->bufferType;
  614. unsigned int bufferSlot = args->bufferSlot;
  615. float* P = args->P;
  616. float* dPdu = args->dPdu;
  617. float* ddPdudu = args->ddPdudu;
  618. unsigned int valueCount = args->valueCount;
  619. /* we interpolate vertex attributes linearly for hermite basis */
  620. if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE)
  621. {
  622. assert(bufferSlot <= vertexAttribs.size());
  623. const char* vsrc = vertexAttribs[bufferSlot].getPtr();
  624. const size_t vstride = vertexAttribs[bufferSlot].getStride();
  625. for (unsigned int i=0; i<valueCount; i+=N)
  626. {
  627. const size_t ofs = i*sizeof(float);
  628. const size_t index = curves[primID];
  629. const vbool<N> valid = vint<N>((int)i)+vint<N>(step) < vint<N>((int)valueCount);
  630. const vfloat<N> p0 = mem<vfloat<N>>::loadu(valid,(float*)&vsrc[(index+0)*vstride+ofs]);
  631. const vfloat<N> p1 = mem<vfloat<N>>::loadu(valid,(float*)&vsrc[(index+1)*vstride+ofs]);
  632. if (P ) mem<vfloat<N>>::storeu(valid,P+i, madd(1.0f-u,p0,u*p1));
  633. if (dPdu ) mem<vfloat<N>>::storeu(valid,dPdu+i, p1-p0);
  634. if (ddPdudu) mem<vfloat<N>>::storeu(valid,ddPdudu+i,vfloat<N>(zero));
  635. }
  636. }
  637. /* interpolation for vertex buffers */
  638. else
  639. {
  640. assert(bufferSlot < numTimeSteps);
  641. const char* vsrc = vertices[bufferSlot].getPtr();
  642. const char* tsrc = tangents[bufferSlot].getPtr();
  643. const size_t vstride = vertices[bufferSlot].getStride();
  644. const size_t tstride = vertices[bufferSlot].getStride();
  645. for (unsigned int i=0; i<valueCount; i+=N)
  646. {
  647. const size_t ofs = i*sizeof(float);
  648. const size_t index = curves[primID];
  649. const vbool<N> valid = vint<N>((int)i)+vint<N>(step) < vint<N>((int)valueCount);
  650. const vfloat<N> p0 = mem<vfloat<N>>::loadu(valid,(float*)&vsrc[(index+0)*vstride+ofs]);
  651. const vfloat<N> p1 = mem<vfloat<N>>::loadu(valid,(float*)&vsrc[(index+1)*vstride+ofs]);
  652. const vfloat<N> t0 = mem<vfloat<N>>::loadu(valid,(float*)&tsrc[(index+0)*tstride+ofs]);
  653. const vfloat<N> t1 = mem<vfloat<N>>::loadu(valid,(float*)&tsrc[(index+1)*tstride+ofs]);
  654. const HermiteCurveT<vfloat<N>> curve(p0,t0,p1,t1);
  655. if (P ) mem<vfloat<N>>::storeu(valid,P+i, curve.eval(u));
  656. if (dPdu ) mem<vfloat<N>>::storeu(valid,dPdu+i, curve.eval_du(u));
  657. if (ddPdudu) mem<vfloat<N>>::storeu(valid,ddPdudu+i,curve.eval_dudu(u));
  658. }
  659. }
  660. }
  661. void interpolate(const RTCInterpolateArguments* const args) {
  662. interpolate_impl<4>(args);
  663. }
  664. };
  665. }
  666. DECLARE_ISA_FUNCTION(CurveGeometry*, createCurves, Device* COMMA Geometry::GType);
  667. }