scene_bezier_curves.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. // ======================================================================== //
  2. // Copyright 2009-2017 Intel Corporation //
  3. // //
  4. // Licensed under the Apache License, Version 2.0 (the "License"); //
  5. // you may not use this file except in compliance with the License. //
  6. // You may obtain a copy of the License at //
  7. // //
  8. // http://www.apache.org/licenses/LICENSE-2.0 //
  9. // //
  10. // Unless required by applicable law or agreed to in writing, software //
  11. // distributed under the License is distributed on an "AS IS" BASIS, //
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
  13. // See the License for the specific language governing permissions and //
  14. // limitations under the License. //
  15. // ======================================================================== //
  16. #pragma once
  17. #include "default.h"
  18. #include "geometry.h"
  19. #include "buffer.h"
  20. #include "../subdiv/bezier_curve.h"
  21. #include "../subdiv/bspline_curve.h"
  22. namespace embree
  23. {
  24. /*! represents an array of bicubic bezier curves */
  25. struct NativeCurves : public Geometry
  26. {
  27. /*! type of this geometry */
  28. static const Geometry::Type geom_type = Geometry::BEZIER_CURVES;
  29. /*! this geometry represents approximate hair geometry and real bezier surface geometry */
  30. enum SubType { HAIR = 1, SURFACE = 0 };
  31. /*! specified the basis the user specified vertices are stored in */
  32. enum Basis { BEZIER = 0, BSPLINE = 1 };
  33. public:
  34. /*! bezier curve construction */
  35. NativeCurves (Scene* parent, SubType subtype, Basis basis, RTCGeometryFlags flags, size_t numPrimitives, size_t numVertices, size_t numTimeSteps);
  36. public:
  37. void enabling();
  38. void disabling();
  39. void setMask (unsigned mask);
  40. void setBuffer(RTCBufferType type, void* ptr, size_t offset, size_t stride, size_t size);
  41. void* map(RTCBufferType type);
  42. void unmap(RTCBufferType type);
  43. void immutable ();
  44. bool verify ();
  45. void interpolate(unsigned primID, float u, float v, RTCBufferType buffer, float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv, size_t numFloats);
  46. template<typename Curve>
  47. void interpolate_helper(unsigned primID, float u, float v, RTCBufferType buffer, float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv, size_t numFloats);
  48. void setTessellationRate(float N);
  49. // FIXME: implement interpolateN
  50. void preCommit();
  51. template<typename InputCurve3fa> void commit_helper();
  52. public:
  53. /*! returns number of bezier curves */
  54. __forceinline size_t size() const {
  55. return curves.size();
  56. }
  57. /*! returns the number of vertices */
  58. __forceinline size_t numVertices() const {
  59. return vertices[0].size();
  60. }
  61. /*! returns the number of vertices */
  62. __forceinline size_t numNativeVertices() const {
  63. return native_vertices[0].size();
  64. }
  65. /*! returns the i'th curve */
  66. __forceinline const unsigned int& curve(size_t i) const {
  67. return native_curves[i];
  68. }
  69. /*! returns the i'th curve */
  70. __forceinline const Curve3fa getCurve(size_t i, size_t itime = 0) const
  71. {
  72. const unsigned int index = curve(i);
  73. const Vec3fa v0 = vertex(index+0,itime);
  74. const Vec3fa v1 = vertex(index+1,itime);
  75. const Vec3fa v2 = vertex(index+2,itime);
  76. const Vec3fa v3 = vertex(index+3,itime);
  77. return Curve3fa (v0,v1,v2,v3);
  78. }
  79. /*! returns i'th vertex of the first time step */
  80. __forceinline Vec3fa vertex(size_t i) const {
  81. return native_vertices0[i];
  82. }
  83. /*! returns i'th radius of the first time step */
  84. __forceinline float radius(size_t i) const {
  85. return native_vertices0[i].w;
  86. }
  87. /*! returns i'th vertex of itime'th timestep */
  88. __forceinline Vec3fa vertex(size_t i, size_t itime) const {
  89. return native_vertices[itime][i];
  90. }
  91. /*! returns i'th radius of itime'th timestep */
  92. __forceinline float radius(size_t i, size_t itime) const {
  93. return native_vertices[itime][i].w;
  94. }
  95. /*! gathers the curve starting with i'th vertex of itime'th timestep */
  96. __forceinline void gather(Vec3fa& p0,
  97. Vec3fa& p1,
  98. Vec3fa& p2,
  99. Vec3fa& p3,
  100. size_t i,
  101. size_t itime = 0) const
  102. {
  103. p0 = vertex(i+0,itime);
  104. p1 = vertex(i+1,itime);
  105. p2 = vertex(i+2,itime);
  106. p3 = vertex(i+3,itime);
  107. }
  108. __forceinline void gather(Vec3fa& p0,
  109. Vec3fa& p1,
  110. Vec3fa& p2,
  111. Vec3fa& p3,
  112. size_t i,
  113. float time) const
  114. {
  115. float ftime;
  116. const size_t itime = getTimeSegment(time, fnumTimeSegments, ftime);
  117. const float t0 = 1.0f - ftime;
  118. const float t1 = ftime;
  119. Vec3fa a0,a1,a2,a3;
  120. gather(a0,a1,a2,a3,i,itime);
  121. Vec3fa b0,b1,b2,b3;
  122. gather(b0,b1,b2,b3,i,itime+1);
  123. p0 = madd(Vec3fa(t0),a0,t1*b0);
  124. p1 = madd(Vec3fa(t0),a1,t1*b1);
  125. p2 = madd(Vec3fa(t0),a2,t1*b2);
  126. p3 = madd(Vec3fa(t0),a3,t1*b3);
  127. }
  128. /*! calculates bounding box of i'th bezier curve */
  129. __forceinline BBox3fa bounds(size_t i, size_t itime = 0) const
  130. {
  131. const Curve3fa curve = getCurve(i,itime);
  132. if (likely(subtype == HAIR)) return curve.tessellatedBounds(tessellationRate);
  133. else return curve.accurateBounds();
  134. }
  135. /*! calculates bounding box of i'th bezier curve */
  136. __forceinline BBox3fa bounds(const AffineSpace3fa& space, size_t i, size_t itime = 0) const
  137. {
  138. const unsigned int index = curve(i);
  139. const Vec3fa v0 = vertex(index+0,itime);
  140. const Vec3fa v1 = vertex(index+1,itime);
  141. const Vec3fa v2 = vertex(index+2,itime);
  142. const Vec3fa v3 = vertex(index+3,itime);
  143. Vec3fa w0 = xfmPoint(space,v0); w0.w = v0.w;
  144. Vec3fa w1 = xfmPoint(space,v1); w1.w = v1.w;
  145. Vec3fa w2 = xfmPoint(space,v2); w2.w = v2.w;
  146. Vec3fa w3 = xfmPoint(space,v3); w3.w = v3.w;
  147. const Curve3fa curve(w0,w1,w2,w3);
  148. if (likely(subtype == HAIR)) return curve.tessellatedBounds(tessellationRate);
  149. else return curve.accurateBounds();
  150. }
  151. /*! check if the i'th primitive is valid at the itime'th timestep */
  152. __forceinline bool valid(size_t i, size_t itime) const {
  153. return valid(i, make_range(itime, itime));
  154. }
  155. /*! check if the i'th primitive is valid at the itime'th time step */
  156. __forceinline bool valid(size_t i, const range<size_t>& itime_range) const
  157. {
  158. const unsigned int index = curve(i);
  159. if (index+3 >= numNativeVertices()) return false;
  160. for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
  161. {
  162. const float r0 = radius(index+0,itime);
  163. const float r1 = radius(index+1,itime);
  164. const float r2 = radius(index+2,itime);
  165. const float r3 = radius(index+3,itime);
  166. if (!isvalid(r0) || !isvalid(r1) || !isvalid(r2) || !isvalid(r3))
  167. return false;
  168. if (min(r0,r1,r2,r3) < 0.0f)
  169. return false;
  170. const Vec3fa v0 = vertex(index+0,itime);
  171. const Vec3fa v1 = vertex(index+1,itime);
  172. const Vec3fa v2 = vertex(index+2,itime);
  173. const Vec3fa v3 = vertex(index+3,itime);
  174. if (!isvalid(v0) || !isvalid(v1) || !isvalid(v2) || !isvalid(v3))
  175. return false;
  176. }
  177. return true;
  178. }
  179. /*! calculates the linear bounds of the i'th primitive at the itimeGlobal'th time segment */
  180. __forceinline LBBox3fa linearBounds(size_t i, size_t itimeGlobal, size_t numTimeStepsGlobal) const
  181. {
  182. return Geometry::linearBounds([&] (size_t itime) { return bounds(i, itime); },
  183. itimeGlobal, numTimeStepsGlobal, numTimeSteps);
  184. }
  185. /*! calculates the linear bounds of the i'th primitive at the itimeGlobal'th time segment */
  186. __forceinline LBBox3fa linearBounds(const AffineSpace3fa& space, size_t i, size_t itimeGlobal, size_t numTimeStepsGlobal) const
  187. {
  188. return Geometry::linearBounds([&] (size_t itime) { return bounds(space, i, itime); },
  189. itimeGlobal, numTimeStepsGlobal, numTimeSteps);
  190. }
  191. /*! calculates the build bounds of the i'th primitive, if it's valid */
  192. __forceinline bool buildBounds(size_t i, BBox3fa* bbox = nullptr) const
  193. {
  194. const unsigned int index = curve(i);
  195. if (index+3 >= numNativeVertices()) return false;
  196. for (size_t t=0; t<numTimeSteps; t++)
  197. {
  198. const float r0 = radius(index+0,t);
  199. const float r1 = radius(index+1,t);
  200. const float r2 = radius(index+2,t);
  201. const float r3 = radius(index+3,t);
  202. if (!isvalid(r0) || !isvalid(r1) || !isvalid(r2) || !isvalid(r3))
  203. return false;
  204. //if (min(r0,r1,r2,r3) < 0.0f)
  205. // return false;
  206. const Vec3fa v0 = vertex(index+0,t);
  207. const Vec3fa v1 = vertex(index+1,t);
  208. const Vec3fa v2 = vertex(index+2,t);
  209. const Vec3fa v3 = vertex(index+3,t);
  210. if (!isvalid(v0) || !isvalid(v1) || !isvalid(v2) || !isvalid(v3))
  211. return false;
  212. }
  213. if (bbox) *bbox = bounds(i);
  214. return true;
  215. }
  216. /*! calculates the i'th build primitive at the itime'th time segment, if it's valid */
  217. __forceinline bool buildPrim(size_t i, size_t itime, Vec3fa& c0, Vec3fa& c1, Vec3fa& c2, Vec3fa& c3) const
  218. {
  219. const unsigned int index = curve(i);
  220. if (index+3 >= numNativeVertices()) return false;
  221. const Vec3fa a0 = vertex(index+0,itime+0); if (unlikely(!isvalid((vfloat4)a0))) return false;
  222. const Vec3fa a1 = vertex(index+1,itime+0); if (unlikely(!isvalid((vfloat4)a1))) return false;
  223. const Vec3fa a2 = vertex(index+2,itime+0); if (unlikely(!isvalid((vfloat4)a2))) return false;
  224. const Vec3fa a3 = vertex(index+3,itime+0); if (unlikely(!isvalid((vfloat4)a3))) return false;
  225. const Vec3fa b0 = vertex(index+0,itime+1); if (unlikely(!isvalid((vfloat4)b0))) return false;
  226. const Vec3fa b1 = vertex(index+1,itime+1); if (unlikely(!isvalid((vfloat4)b1))) return false;
  227. const Vec3fa b2 = vertex(index+2,itime+1); if (unlikely(!isvalid((vfloat4)b2))) return false;
  228. const Vec3fa b3 = vertex(index+3,itime+1); if (unlikely(!isvalid((vfloat4)b3))) return false;
  229. if (unlikely(min(a0.w,a1.w,a2.w,a3.w) < 0.0f)) return false;
  230. if (unlikely(min(b0.w,b1.w,b2.w,b3.w) < 0.0f)) return false;
  231. c0 = 0.5f*(a0+b0);
  232. c1 = 0.5f*(a1+b1);
  233. c2 = 0.5f*(a2+b2);
  234. c3 = 0.5f*(a3+b3);
  235. return true;
  236. }
  237. /*! calculates the i'th build primitive at the itimeGlobal'th time segment, if it's valid */
  238. __forceinline bool buildPrim(size_t i, size_t itimeGlobal, size_t numTimeStepsGlobal, Vec3fa& c0, Vec3fa& c1, Vec3fa& c2, Vec3fa& c3) const
  239. {
  240. if (!Geometry::validLinearBounds([&] (size_t itime) { return valid(i, itime); },
  241. itimeGlobal, numTimeStepsGlobal, numTimeSteps))
  242. return false;
  243. const unsigned int index = curve(i);
  244. float time = (float(int(itimeGlobal)) + 0.5f) / float(int(numTimeStepsGlobal-1));
  245. gather(c0,c1,c2,c3,index,time);
  246. return true;
  247. }
  248. public:
  249. APIBuffer<unsigned int> curves; //!< array of curve indices
  250. vector<APIBuffer<Vec3fa>> vertices; //!< vertex array for each timestep
  251. vector<APIBuffer<char>> userbuffers; //!< user buffers
  252. SubType subtype; //!< hair or surface geometry
  253. Basis basis; //!< basis of user provided vertices
  254. int tessellationRate; //!< tessellation rate for bezier curve
  255. public:
  256. BufferRefT<Vec3fa> native_vertices0; //!< fast access to first vertex buffer
  257. APIBuffer<unsigned int> native_curves; //!< array of curve indices
  258. vector<APIBuffer<Vec3fa>> native_vertices; //!< vertex array for each timestep
  259. };
  260. struct CurvesBezier : public NativeCurves
  261. {
  262. CurvesBezier (Scene* parent, SubType subtype, Basis basis, RTCGeometryFlags flags, size_t numPrimitives, size_t numVertices, size_t numTimeSteps);
  263. void preCommit();
  264. void interpolate(unsigned primID, float u, float v, RTCBufferType buffer, float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv, size_t numFloats);
  265. };
  266. struct CurvesBSpline : public NativeCurves
  267. {
  268. CurvesBSpline (Scene* parent, SubType subtype, Basis basis, RTCGeometryFlags flags, size_t numPrimitives, size_t numVertices, size_t numTimeSteps);
  269. void preCommit();
  270. void interpolate(unsigned primID, float u, float v, RTCBufferType buffer, float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv, size_t numFloats);
  271. };
  272. }