scene_curves.h 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  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 starting with i'th vertex */
  100. __forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, Vec3fa& n0, Vec3fa& n1, Vec3fa& n2, Vec3fa& n3, size_t i) const
  101. {
  102. p0 = vertex(i+0);
  103. p1 = vertex(i+1);
  104. p2 = vertex(i+2);
  105. p3 = vertex(i+3);
  106. n0 = normal(i+0);
  107. n1 = normal(i+1);
  108. n2 = normal(i+2);
  109. n3 = normal(i+3);
  110. }
  111. /*! gathers the curve starting with i'th vertex of itime'th timestep */
  112. __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
  113. {
  114. p0 = vertex(i+0,itime);
  115. p1 = vertex(i+1,itime);
  116. p2 = vertex(i+2,itime);
  117. p3 = vertex(i+3,itime);
  118. n0 = normal(i+0,itime);
  119. n1 = normal(i+1,itime);
  120. n2 = normal(i+2,itime);
  121. n3 = normal(i+3,itime);
  122. }
  123. /*! prefetches the curve starting with i'th vertex of itime'th timestep */
  124. __forceinline void prefetchL1_vertices(size_t i) const
  125. {
  126. prefetchL1(vertices0.getPtr(i)+0);
  127. prefetchL1(vertices0.getPtr(i)+64);
  128. }
  129. /*! prefetches the curve starting with i'th vertex of itime'th timestep */
  130. __forceinline void prefetchL2_vertices(size_t i) const
  131. {
  132. prefetchL2(vertices0.getPtr(i)+0);
  133. prefetchL2(vertices0.getPtr(i)+64);
  134. }
  135. /*! loads curve vertices for specified time */
  136. __forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, size_t i, float time) const
  137. {
  138. float ftime;
  139. const size_t itime = timeSegment(time, ftime);
  140. const float t0 = 1.0f - ftime;
  141. const float t1 = ftime;
  142. Vec3ff a0,a1,a2,a3;
  143. gather(a0,a1,a2,a3,i,itime);
  144. Vec3ff b0,b1,b2,b3;
  145. gather(b0,b1,b2,b3,i,itime+1);
  146. p0 = madd(Vec3ff(t0),a0,t1*b0);
  147. p1 = madd(Vec3ff(t0),a1,t1*b1);
  148. p2 = madd(Vec3ff(t0),a2,t1*b2);
  149. p3 = madd(Vec3ff(t0),a3,t1*b3);
  150. }
  151. /*! loads curve vertices for specified time */
  152. __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
  153. {
  154. float ftime;
  155. const size_t itime = timeSegment(time, ftime);
  156. const float t0 = 1.0f - ftime;
  157. const float t1 = ftime;
  158. Vec3ff a0,a1,a2,a3; Vec3fa an0,an1,an2,an3;
  159. gather(a0,a1,a2,a3,an0,an1,an2,an3,i,itime);
  160. Vec3ff b0,b1,b2,b3; Vec3fa bn0,bn1,bn2,bn3;
  161. gather(b0,b1,b2,b3,bn0,bn1,bn2,bn3,i,itime+1);
  162. p0 = madd(Vec3ff(t0),a0,t1*b0);
  163. p1 = madd(Vec3ff(t0),a1,t1*b1);
  164. p2 = madd(Vec3ff(t0),a2,t1*b2);
  165. p3 = madd(Vec3ff(t0),a3,t1*b3);
  166. n0 = madd(Vec3ff(t0),an0,t1*bn0);
  167. n1 = madd(Vec3ff(t0),an1,t1*bn1);
  168. n2 = madd(Vec3ff(t0),an2,t1*bn2);
  169. n3 = madd(Vec3ff(t0),an3,t1*bn3);
  170. }
  171. template<typename SourceCurve3ff, typename SourceCurve3fa, typename TensorLinearCubicBezierSurface3fa>
  172. __forceinline TensorLinearCubicBezierSurface3fa getNormalOrientedCurve(IntersectContext* context, const Vec3fa& ray_org, const unsigned int primID, const size_t itime) const
  173. {
  174. Vec3ff v0,v1,v2,v3; Vec3fa n0,n1,n2,n3;
  175. unsigned int vertexID = curve(primID);
  176. gather(v0,v1,v2,v3,n0,n1,n2,n3,vertexID,itime);
  177. SourceCurve3ff ccurve(v0,v1,v2,v3);
  178. SourceCurve3fa ncurve(n0,n1,n2,n3);
  179. ccurve = enlargeRadiusToMinWidth(context,this,ray_org,ccurve);
  180. return TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(ccurve,ncurve);
  181. }
  182. template<typename SourceCurve3ff, typename SourceCurve3fa, typename TensorLinearCubicBezierSurface3fa>
  183. __forceinline TensorLinearCubicBezierSurface3fa getNormalOrientedCurve(IntersectContext* context, const Vec3fa& ray_org, const unsigned int primID, const float time) const
  184. {
  185. float ftime;
  186. const size_t itime = timeSegment(time, ftime);
  187. const TensorLinearCubicBezierSurface3fa curve0 = getNormalOrientedCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context,ray_org,primID,itime+0);
  188. const TensorLinearCubicBezierSurface3fa curve1 = getNormalOrientedCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context,ray_org,primID,itime+1);
  189. return clerp(curve0,curve1,ftime);
  190. }
  191. /*! gathers the hermite curve starting with i'th vertex */
  192. __forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3ff& p1, Vec3ff& t1, size_t i) const
  193. {
  194. p0 = vertex (i+0);
  195. p1 = vertex (i+1);
  196. t0 = tangent(i+0);
  197. t1 = tangent(i+1);
  198. }
  199. /*! gathers the hermite curve starting with i'th vertex of itime'th timestep */
  200. __forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3ff& p1, Vec3ff& t1, size_t i, size_t itime) const
  201. {
  202. p0 = vertex (i+0,itime);
  203. p1 = vertex (i+1,itime);
  204. t0 = tangent(i+0,itime);
  205. t1 = tangent(i+1,itime);
  206. }
  207. /*! loads curve vertices for specified time */
  208. __forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3ff& p1, Vec3ff& t1, size_t i, float time) const
  209. {
  210. float ftime;
  211. const size_t itime = timeSegment(time, ftime);
  212. const float f0 = 1.0f - ftime, f1 = ftime;
  213. Vec3ff ap0,at0,ap1,at1;
  214. gather_hermite(ap0,at0,ap1,at1,i,itime);
  215. Vec3ff bp0,bt0,bp1,bt1;
  216. gather_hermite(bp0,bt0,bp1,bt1,i,itime+1);
  217. p0 = madd(Vec3ff(f0),ap0,f1*bp0);
  218. t0 = madd(Vec3ff(f0),at0,f1*bt0);
  219. p1 = madd(Vec3ff(f0),ap1,f1*bp1);
  220. t1 = madd(Vec3ff(f0),at1,f1*bt1);
  221. }
  222. /*! gathers the hermite curve starting with i'th vertex */
  223. __forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3fa& n0, Vec3fa& dn0, Vec3ff& p1, Vec3ff& t1, Vec3fa& n1, Vec3fa& dn1, size_t i) const
  224. {
  225. p0 = vertex (i+0);
  226. p1 = vertex (i+1);
  227. t0 = tangent(i+0);
  228. t1 = tangent(i+1);
  229. n0 = normal(i+0);
  230. n1 = normal(i+1);
  231. dn0 = dnormal(i+0);
  232. dn1 = dnormal(i+1);
  233. }
  234. /*! gathers the hermite curve starting with i'th vertex of itime'th timestep */
  235. __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
  236. {
  237. p0 = vertex (i+0,itime);
  238. p1 = vertex (i+1,itime);
  239. t0 = tangent(i+0,itime);
  240. t1 = tangent(i+1,itime);
  241. n0 = normal(i+0,itime);
  242. n1 = normal(i+1,itime);
  243. dn0 = dnormal(i+0,itime);
  244. dn1 = dnormal(i+1,itime);
  245. }
  246. /*! loads curve vertices for specified time */
  247. __forceinline void gather_hermite(Vec3ff& p0, Vec3fa& t0, Vec3fa& n0, Vec3fa& dn0, Vec3ff& p1, Vec3fa& t1, Vec3fa& n1, Vec3fa& dn1, size_t i, float time) const
  248. {
  249. float ftime;
  250. const size_t itime = timeSegment(time, ftime);
  251. const float f0 = 1.0f - ftime, f1 = ftime;
  252. Vec3ff ap0,at0,ap1,at1; Vec3fa an0,adn0,an1,adn1;
  253. gather_hermite(ap0,at0,an0,adn0,ap1,at1,an1,adn1,i,itime);
  254. Vec3ff bp0,bt0,bp1,bt1; Vec3fa bn0,bdn0,bn1,bdn1;
  255. gather_hermite(bp0,bt0,bn0,bdn0,bp1,bt1,bn1,bdn1,i,itime+1);
  256. p0 = madd(Vec3ff(f0),ap0,f1*bp0);
  257. t0 = madd(Vec3ff(f0),at0,f1*bt0);
  258. n0 = madd(Vec3ff(f0),an0,f1*bn0);
  259. dn0= madd(Vec3ff(f0),adn0,f1*bdn0);
  260. p1 = madd(Vec3ff(f0),ap1,f1*bp1);
  261. t1 = madd(Vec3ff(f0),at1,f1*bt1);
  262. n1 = madd(Vec3ff(f0),an1,f1*bn1);
  263. dn1= madd(Vec3ff(f0),adn1,f1*bdn1);
  264. }
  265. template<typename SourceCurve3ff, typename SourceCurve3fa, typename TensorLinearCubicBezierSurface3fa>
  266. __forceinline TensorLinearCubicBezierSurface3fa getNormalOrientedHermiteCurve(IntersectContext* context, const Vec3fa& ray_org, const unsigned int primID, const size_t itime) const
  267. {
  268. Vec3ff v0,t0,v1,t1; Vec3fa n0,dn0,n1,dn1;
  269. unsigned int vertexID = curve(primID);
  270. gather_hermite(v0,t0,n0,dn0,v1,t1,n1,dn1,vertexID,itime);
  271. SourceCurve3ff ccurve(v0,t0,v1,t1);
  272. SourceCurve3fa ncurve(n0,dn0,n1,dn1);
  273. ccurve = enlargeRadiusToMinWidth(context,this,ray_org,ccurve);
  274. return TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(ccurve,ncurve);
  275. }
  276. template<typename SourceCurve3ff, typename SourceCurve3fa, typename TensorLinearCubicBezierSurface3fa>
  277. __forceinline TensorLinearCubicBezierSurface3fa getNormalOrientedHermiteCurve(IntersectContext* context, const Vec3fa& ray_org, const unsigned int primID, const float time) const
  278. {
  279. float ftime;
  280. const size_t itime = timeSegment(time, ftime);
  281. const TensorLinearCubicBezierSurface3fa curve0 = getNormalOrientedHermiteCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,itime+0);
  282. const TensorLinearCubicBezierSurface3fa curve1 = getNormalOrientedHermiteCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,itime+1);
  283. return clerp(curve0,curve1,ftime);
  284. }
  285. private:
  286. void resizeBuffers(unsigned int numSteps);
  287. public:
  288. BufferView<unsigned int> curves; //!< array of curve indices
  289. BufferView<Vec3ff> vertices0; //!< fast access to first vertex buffer
  290. BufferView<Vec3fa> normals0; //!< fast access to first normal buffer
  291. BufferView<Vec3ff> tangents0; //!< fast access to first tangent buffer
  292. BufferView<Vec3fa> dnormals0; //!< fast access to first normal derivative buffer
  293. vector<BufferView<Vec3ff>> vertices; //!< vertex array for each timestep
  294. vector<BufferView<Vec3fa>> normals; //!< normal array for each timestep
  295. vector<BufferView<Vec3ff>> tangents; //!< tangent array for each timestep
  296. vector<BufferView<Vec3fa>> dnormals; //!< normal derivative array for each timestep
  297. BufferView<char> flags; //!< start, end flag per segment
  298. vector<BufferView<char>> vertexAttribs; //!< user buffers
  299. int tessellationRate; //!< tessellation rate for flat curve
  300. float maxRadiusScale = 1.0; //!< maximal min-width scaling of curve radii
  301. };
  302. namespace isa
  303. {
  304. template<template<typename Ty> class Curve>
  305. struct CurveGeometryInterface : public CurveGeometry
  306. {
  307. typedef Curve<Vec3ff> Curve3ff;
  308. typedef Curve<Vec3fa> Curve3fa;
  309. CurveGeometryInterface (Device* device, Geometry::GType gtype)
  310. : CurveGeometry(device,gtype) {}
  311. __forceinline const Curve3ff getCurveScaledRadius(size_t i, size_t itime = 0) const
  312. {
  313. const unsigned int index = curve(i);
  314. Vec3ff v0 = vertex(index+0,itime);
  315. Vec3ff v1 = vertex(index+1,itime);
  316. Vec3ff v2 = vertex(index+2,itime);
  317. Vec3ff v3 = vertex(index+3,itime);
  318. v0.w *= maxRadiusScale;
  319. v1.w *= maxRadiusScale;
  320. v2.w *= maxRadiusScale;
  321. v3.w *= maxRadiusScale;
  322. return Curve3ff (v0,v1,v2,v3);
  323. }
  324. __forceinline const Curve3ff getCurveScaledRadius(const LinearSpace3fa& space, size_t i, size_t itime = 0) const
  325. {
  326. const unsigned int index = curve(i);
  327. const Vec3ff v0 = vertex(index+0,itime);
  328. const Vec3ff v1 = vertex(index+1,itime);
  329. const Vec3ff v2 = vertex(index+2,itime);
  330. const Vec3ff v3 = vertex(index+3,itime);
  331. const Vec3ff w0(xfmPoint(space,(Vec3fa)v0), maxRadiusScale*v0.w);
  332. const Vec3ff w1(xfmPoint(space,(Vec3fa)v1), maxRadiusScale*v1.w);
  333. const Vec3ff w2(xfmPoint(space,(Vec3fa)v2), maxRadiusScale*v2.w);
  334. const Vec3ff w3(xfmPoint(space,(Vec3fa)v3), maxRadiusScale*v3.w);
  335. return Curve3ff(w0,w1,w2,w3);
  336. }
  337. __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
  338. {
  339. const float r_scale = r_scale0*scale;
  340. const unsigned int index = curve(i);
  341. const Vec3ff v0 = vertex(index+0,itime);
  342. const Vec3ff v1 = vertex(index+1,itime);
  343. const Vec3ff v2 = vertex(index+2,itime);
  344. const Vec3ff v3 = vertex(index+3,itime);
  345. const Vec3ff w0(xfmPoint(space,((Vec3fa)v0-ofs)*Vec3fa(scale)), maxRadiusScale*v0.w*r_scale);
  346. const Vec3ff w1(xfmPoint(space,((Vec3fa)v1-ofs)*Vec3fa(scale)), maxRadiusScale*v1.w*r_scale);
  347. const Vec3ff w2(xfmPoint(space,((Vec3fa)v2-ofs)*Vec3fa(scale)), maxRadiusScale*v2.w*r_scale);
  348. const Vec3ff w3(xfmPoint(space,((Vec3fa)v3-ofs)*Vec3fa(scale)), maxRadiusScale*v3.w*r_scale);
  349. return Curve3ff(w0,w1,w2,w3);
  350. }
  351. __forceinline const Curve3fa getNormalCurve(size_t i, size_t itime = 0) const
  352. {
  353. const unsigned int index = curve(i);
  354. const Vec3fa n0 = normal(index+0,itime);
  355. const Vec3fa n1 = normal(index+1,itime);
  356. const Vec3fa n2 = normal(index+2,itime);
  357. const Vec3fa n3 = normal(index+3,itime);
  358. return Curve3fa (n0,n1,n2,n3);
  359. }
  360. __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(size_t i, size_t itime = 0) const
  361. {
  362. const Curve3ff center = getCurveScaledRadius(i,itime);
  363. const Curve3fa normal = getNormalCurve(i,itime);
  364. const TensorLinearCubicBezierSurface3fa ocurve = TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(center,normal);
  365. return ocurve;
  366. }
  367. __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(const LinearSpace3fa& space, size_t i, size_t itime = 0) const {
  368. return getOrientedCurveScaledRadius(i,itime).xfm(space);
  369. }
  370. __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(const Vec3fa& ofs, const float scale, const LinearSpace3fa& space, size_t i, size_t itime = 0) const {
  371. return getOrientedCurveScaledRadius(i,itime).xfm(space,ofs,scale);
  372. }
  373. /*! check if the i'th primitive is valid at the itime'th time step */
  374. __forceinline bool valid(Geometry::GType ctype, size_t i, const range<size_t>& itime_range) const
  375. {
  376. const unsigned int index = curve(i);
  377. if (index+3 >= numVertices()) return false;
  378. for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
  379. {
  380. const float r0 = radius(index+0,itime);
  381. const float r1 = radius(index+1,itime);
  382. const float r2 = radius(index+2,itime);
  383. const float r3 = radius(index+3,itime);
  384. if (!isvalid(r0) || !isvalid(r1) || !isvalid(r2) || !isvalid(r3))
  385. return false;
  386. const Vec3fa v0 = vertex(index+0,itime);
  387. const Vec3fa v1 = vertex(index+1,itime);
  388. const Vec3fa v2 = vertex(index+2,itime);
  389. const Vec3fa v3 = vertex(index+3,itime);
  390. if (!isvalid(v0) || !isvalid(v1) || !isvalid(v2) || !isvalid(v3))
  391. return false;
  392. if (ctype == Geometry::GTY_SUBTYPE_ORIENTED_CURVE)
  393. {
  394. const Vec3fa n0 = normal(index+0,itime);
  395. const Vec3fa n1 = normal(index+1,itime);
  396. if (!isvalid(n0) || !isvalid(n1))
  397. return false;
  398. const BBox3fa b = getOrientedCurveScaledRadius(i,itime).accurateBounds();
  399. if (!isvalid(b))
  400. return false;
  401. }
  402. }
  403. return true;
  404. }
  405. template<int N>
  406. void interpolate_impl(const RTCInterpolateArguments* const args)
  407. {
  408. unsigned int primID = args->primID;
  409. float u = args->u;
  410. RTCBufferType bufferType = args->bufferType;
  411. unsigned int bufferSlot = args->bufferSlot;
  412. float* P = args->P;
  413. float* dPdu = args->dPdu;
  414. float* ddPdudu = args->ddPdudu;
  415. unsigned int valueCount = args->valueCount;
  416. /* calculate base pointer and stride */
  417. assert((bufferType == RTC_BUFFER_TYPE_VERTEX && bufferSlot < numTimeSteps) ||
  418. (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE && bufferSlot <= vertexAttribs.size()));
  419. const char* src = nullptr;
  420. size_t stride = 0;
  421. if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE) {
  422. src = vertexAttribs[bufferSlot].getPtr();
  423. stride = vertexAttribs[bufferSlot].getStride();
  424. } else {
  425. src = vertices[bufferSlot].getPtr();
  426. stride = vertices[bufferSlot].getStride();
  427. }
  428. for (unsigned int i=0; i<valueCount; i+=N)
  429. {
  430. size_t ofs = i*sizeof(float);
  431. const size_t index = curves[primID];
  432. const vbool<N> valid = vint<N>((int)i)+vint<N>(step) < vint<N>((int)valueCount);
  433. const vfloat<N> p0 = mem<vfloat<N>>::loadu(valid,(float*)&src[(index+0)*stride+ofs]);
  434. const vfloat<N> p1 = mem<vfloat<N>>::loadu(valid,(float*)&src[(index+1)*stride+ofs]);
  435. const vfloat<N> p2 = mem<vfloat<N>>::loadu(valid,(float*)&src[(index+2)*stride+ofs]);
  436. const vfloat<N> p3 = mem<vfloat<N>>::loadu(valid,(float*)&src[(index+3)*stride+ofs]);
  437. const Curve<vfloat<N>> curve(p0,p1,p2,p3);
  438. if (P ) mem<vfloat<N>>::storeu(valid,P+i, curve.eval(u));
  439. if (dPdu ) mem<vfloat<N>>::storeu(valid,dPdu+i, curve.eval_du(u));
  440. if (ddPdudu) mem<vfloat<N>>::storeu(valid,ddPdudu+i,curve.eval_dudu(u));
  441. }
  442. }
  443. void interpolate(const RTCInterpolateArguments* const args) {
  444. interpolate_impl<4>(args);
  445. }
  446. };
  447. template<template<typename Ty> class Curve>
  448. struct HermiteCurveGeometryInterface : public CurveGeometry
  449. {
  450. typedef Curve<Vec3ff> HermiteCurve3ff;
  451. typedef Curve<Vec3fa> HermiteCurve3fa;
  452. HermiteCurveGeometryInterface (Device* device, Geometry::GType gtype)
  453. : CurveGeometry(device,gtype) {}
  454. __forceinline const HermiteCurve3ff getCurveScaledRadius(size_t i, size_t itime = 0) const
  455. {
  456. const unsigned int index = curve(i);
  457. Vec3ff v0 = vertex(index+0,itime);
  458. Vec3ff v1 = vertex(index+1,itime);
  459. Vec3ff t0 = tangent(index+0,itime);
  460. Vec3ff t1 = tangent(index+1,itime);
  461. v0.w *= maxRadiusScale;
  462. v1.w *= maxRadiusScale;
  463. t0.w *= maxRadiusScale;
  464. t1.w *= maxRadiusScale;
  465. return HermiteCurve3ff (v0,t0,v1,t1);
  466. }
  467. __forceinline const HermiteCurve3ff getCurveScaledRadius(const LinearSpace3fa& space, size_t i, size_t itime = 0) const
  468. {
  469. const unsigned int index = curve(i);
  470. const Vec3ff v0 = vertex(index+0,itime);
  471. const Vec3ff v1 = vertex(index+1,itime);
  472. const Vec3ff t0 = tangent(index+0,itime);
  473. const Vec3ff t1 = tangent(index+1,itime);
  474. const Vec3ff V0(xfmPoint(space,(Vec3fa)v0),maxRadiusScale*v0.w);
  475. const Vec3ff V1(xfmPoint(space,(Vec3fa)v1),maxRadiusScale*v1.w);
  476. const Vec3ff T0(xfmVector(space,(Vec3fa)t0),maxRadiusScale*t0.w);
  477. const Vec3ff T1(xfmVector(space,(Vec3fa)t1),maxRadiusScale*t1.w);
  478. return HermiteCurve3ff(V0,T0,V1,T1);
  479. }
  480. __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
  481. {
  482. const float r_scale = r_scale0*scale;
  483. const unsigned int index = curve(i);
  484. const Vec3ff v0 = vertex(index+0,itime);
  485. const Vec3ff v1 = vertex(index+1,itime);
  486. const Vec3ff t0 = tangent(index+0,itime);
  487. const Vec3ff t1 = tangent(index+1,itime);
  488. const Vec3ff V0(xfmPoint(space,(v0-ofs)*Vec3fa(scale)), maxRadiusScale*v0.w*r_scale);
  489. const Vec3ff V1(xfmPoint(space,(v1-ofs)*Vec3fa(scale)), maxRadiusScale*v1.w*r_scale);
  490. const Vec3ff T0(xfmVector(space,t0*Vec3fa(scale)), maxRadiusScale*t0.w*r_scale);
  491. const Vec3ff T1(xfmVector(space,t1*Vec3fa(scale)), maxRadiusScale*t1.w*r_scale);
  492. return HermiteCurve3ff(V0,T0,V1,T1);
  493. }
  494. __forceinline const HermiteCurve3fa getNormalCurve(size_t i, size_t itime = 0) const
  495. {
  496. const unsigned int index = curve(i);
  497. const Vec3fa n0 = normal(index+0,itime);
  498. const Vec3fa n1 = normal(index+1,itime);
  499. const Vec3fa dn0 = dnormal(index+0,itime);
  500. const Vec3fa dn1 = dnormal(index+1,itime);
  501. return HermiteCurve3fa (n0,dn0,n1,dn1);
  502. }
  503. __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(size_t i, size_t itime = 0) const
  504. {
  505. const HermiteCurve3ff center = getCurveScaledRadius(i,itime);
  506. const HermiteCurve3fa normal = getNormalCurve(i,itime);
  507. const TensorLinearCubicBezierSurface3fa ocurve = TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(center,normal);
  508. return ocurve;
  509. }
  510. __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(const LinearSpace3fa& space, size_t i, size_t itime = 0) const {
  511. return getOrientedCurveScaledRadius(i,itime).xfm(space);
  512. }
  513. __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(const Vec3fa& ofs, const float scale, const LinearSpace3fa& space, size_t i, size_t itime = 0) const {
  514. return getOrientedCurveScaledRadius(i,itime).xfm(space,ofs,scale);
  515. }
  516. /*! check if the i'th primitive is valid at the itime'th time step */
  517. __forceinline bool valid(Geometry::GType ctype, size_t i, const range<size_t>& itime_range) const
  518. {
  519. const unsigned int index = curve(i);
  520. if (index+1 >= numVertices()) return false;
  521. for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
  522. {
  523. const Vec3ff v0 = vertex(index+0,itime);
  524. const Vec3ff v1 = vertex(index+1,itime);
  525. if (!isvalid4(v0) || !isvalid4(v1))
  526. return false;
  527. const Vec3ff t0 = tangent(index+0,itime);
  528. const Vec3ff t1 = tangent(index+1,itime);
  529. if (!isvalid4(t0) || !isvalid4(t1))
  530. return false;
  531. if (ctype == Geometry::GTY_SUBTYPE_ORIENTED_CURVE)
  532. {
  533. const Vec3fa n0 = normal(index+0,itime);
  534. const Vec3fa n1 = normal(index+1,itime);
  535. if (!isvalid(n0) || !isvalid(n1))
  536. return false;
  537. const Vec3fa dn0 = dnormal(index+0,itime);
  538. const Vec3fa dn1 = dnormal(index+1,itime);
  539. if (!isvalid(dn0) || !isvalid(dn1))
  540. return false;
  541. const BBox3fa b = getOrientedCurveScaledRadius(i,itime).accurateBounds();
  542. if (!isvalid(b))
  543. return false;
  544. }
  545. }
  546. return true;
  547. }
  548. template<int N>
  549. void interpolate_impl(const RTCInterpolateArguments* const args)
  550. {
  551. unsigned int primID = args->primID;
  552. float u = args->u;
  553. RTCBufferType bufferType = args->bufferType;
  554. unsigned int bufferSlot = args->bufferSlot;
  555. float* P = args->P;
  556. float* dPdu = args->dPdu;
  557. float* ddPdudu = args->ddPdudu;
  558. unsigned int valueCount = args->valueCount;
  559. /* we interpolate vertex attributes linearly for hermite basis */
  560. if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE)
  561. {
  562. assert(bufferSlot <= vertexAttribs.size());
  563. const char* vsrc = vertexAttribs[bufferSlot].getPtr();
  564. const size_t vstride = vertexAttribs[bufferSlot].getStride();
  565. for (unsigned int i=0; i<valueCount; i+=N)
  566. {
  567. const size_t ofs = i*sizeof(float);
  568. const size_t index = curves[primID];
  569. const vbool<N> valid = vint<N>((int)i)+vint<N>(step) < vint<N>((int)valueCount);
  570. const vfloat<N> p0 = mem<vfloat<N>>::loadu(valid,(float*)&vsrc[(index+0)*vstride+ofs]);
  571. const vfloat<N> p1 = mem<vfloat<N>>::loadu(valid,(float*)&vsrc[(index+1)*vstride+ofs]);
  572. if (P ) mem<vfloat<N>>::storeu(valid,P+i, madd(1.0f-u,p0,u*p1));
  573. if (dPdu ) mem<vfloat<N>>::storeu(valid,dPdu+i, p1-p0);
  574. if (ddPdudu) mem<vfloat<N>>::storeu(valid,ddPdudu+i,vfloat<N>(zero));
  575. }
  576. }
  577. /* interpolation for vertex buffers */
  578. else
  579. {
  580. assert(bufferSlot < numTimeSteps);
  581. const char* vsrc = vertices[bufferSlot].getPtr();
  582. const char* tsrc = tangents[bufferSlot].getPtr();
  583. const size_t vstride = vertices[bufferSlot].getStride();
  584. const size_t tstride = vertices[bufferSlot].getStride();
  585. for (unsigned int i=0; i<valueCount; i+=N)
  586. {
  587. const size_t ofs = i*sizeof(float);
  588. const size_t index = curves[primID];
  589. const vbool<N> valid = vint<N>((int)i)+vint<N>(step) < vint<N>((int)valueCount);
  590. const vfloat<N> p0 = mem<vfloat<N>>::loadu(valid,(float*)&vsrc[(index+0)*vstride+ofs]);
  591. const vfloat<N> p1 = mem<vfloat<N>>::loadu(valid,(float*)&vsrc[(index+1)*vstride+ofs]);
  592. const vfloat<N> t0 = mem<vfloat<N>>::loadu(valid,(float*)&tsrc[(index+0)*tstride+ofs]);
  593. const vfloat<N> t1 = mem<vfloat<N>>::loadu(valid,(float*)&tsrc[(index+1)*tstride+ofs]);
  594. const HermiteCurveT<vfloat<N>> curve(p0,t0,p1,t1);
  595. if (P ) mem<vfloat<N>>::storeu(valid,P+i, curve.eval(u));
  596. if (dPdu ) mem<vfloat<N>>::storeu(valid,dPdu+i, curve.eval_du(u));
  597. if (ddPdudu) mem<vfloat<N>>::storeu(valid,ddPdudu+i,curve.eval_dudu(u));
  598. }
  599. }
  600. }
  601. void interpolate(const RTCInterpolateArguments* const args) {
  602. interpolate_impl<4>(args);
  603. }
  604. };
  605. }
  606. DECLARE_ISA_FUNCTION(CurveGeometry*, createCurves, Device* COMMA Geometry::GType);
  607. }