scene_bezier_curves.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  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. #include "scene_bezier_curves.h"
  17. #include "scene.h"
  18. namespace embree
  19. {
  20. NativeCurves::NativeCurves (Scene* parent, SubType subtype, Basis basis, RTCGeometryFlags flags, size_t numPrimitives, size_t numVertices, size_t numTimeSteps)
  21. : Geometry(parent,BEZIER_CURVES,numPrimitives,numTimeSteps,flags), subtype(subtype), basis(basis), tessellationRate(4)
  22. {
  23. curves.init(parent->device,numPrimitives,sizeof(int));
  24. vertices.resize(numTimeSteps);
  25. for (size_t i=0; i<numTimeSteps; i++) {
  26. vertices[i].init(parent->device,numVertices,sizeof(Vec3fa));
  27. }
  28. enabling();
  29. }
  30. void NativeCurves::enabling()
  31. {
  32. if (numTimeSteps == 1) parent->world.numBezierCurves += numPrimitives;
  33. else parent->worldMB.numBezierCurves += numPrimitives;
  34. }
  35. void NativeCurves::disabling()
  36. {
  37. if (numTimeSteps == 1) parent->world.numBezierCurves -= numPrimitives;
  38. else parent->worldMB.numBezierCurves -= numPrimitives;
  39. }
  40. void NativeCurves::setMask (unsigned mask)
  41. {
  42. if (parent->isStatic() && parent->isBuild())
  43. throw_RTCError(RTC_INVALID_OPERATION,"static geometries cannot get modified");
  44. this->mask = mask;
  45. Geometry::update();
  46. }
  47. void NativeCurves::setBuffer(RTCBufferType type, void* ptr, size_t offset, size_t stride, size_t size)
  48. {
  49. if (parent->isStatic() && parent->isBuild())
  50. throw_RTCError(RTC_INVALID_OPERATION,"static geometries cannot get modified");
  51. /* verify that all accesses are 4 bytes aligned */
  52. if (((size_t(ptr) + offset) & 0x3) || (stride & 0x3))
  53. throw_RTCError(RTC_INVALID_OPERATION,"data must be 4 bytes aligned");
  54. unsigned bid = type & 0xFFFF;
  55. if (type >= RTC_VERTEX_BUFFER0 && type < RTCBufferType(RTC_VERTEX_BUFFER0 + numTimeSteps))
  56. {
  57. size_t t = type - RTC_VERTEX_BUFFER0;
  58. vertices[t].set(ptr,offset,stride,size);
  59. vertices[t].checkPadding16();
  60. }
  61. else if (type >= RTC_USER_VERTEX_BUFFER0 && type < RTC_USER_VERTEX_BUFFER0+RTC_MAX_USER_VERTEX_BUFFERS)
  62. {
  63. if (bid >= userbuffers.size()) userbuffers.resize(bid+1);
  64. userbuffers[bid] = APIBuffer<char>(parent->device,numVertices(),stride);
  65. userbuffers[bid].set(ptr,offset,stride,size);
  66. userbuffers[bid].checkPadding16();
  67. }
  68. else if (type == RTC_INDEX_BUFFER)
  69. {
  70. if (size != (size_t)-1) disabling();
  71. curves.set(ptr,offset,stride,size);
  72. setNumPrimitives(size);
  73. if (size != (size_t)-1) enabling();
  74. }
  75. else
  76. throw_RTCError(RTC_INVALID_ARGUMENT,"unknown buffer type");
  77. }
  78. void* NativeCurves::map(RTCBufferType type)
  79. {
  80. if (parent->isStatic() && parent->isBuild()) {
  81. throw_RTCError(RTC_INVALID_OPERATION,"static geometries cannot get modified");
  82. return nullptr;
  83. }
  84. if (type == RTC_INDEX_BUFFER) {
  85. return curves.map(parent->numMappedBuffers);
  86. }
  87. else if (type >= RTC_VERTEX_BUFFER0 && type < RTCBufferType(RTC_VERTEX_BUFFER0 + numTimeSteps)) {
  88. return vertices[type - RTC_VERTEX_BUFFER0].map(parent->numMappedBuffers);
  89. }
  90. else {
  91. throw_RTCError(RTC_INVALID_ARGUMENT,"unknown buffer type");
  92. return nullptr;
  93. }
  94. }
  95. void NativeCurves::unmap(RTCBufferType type)
  96. {
  97. if (parent->isStatic() && parent->isBuild())
  98. throw_RTCError(RTC_INVALID_OPERATION,"static geometries cannot get modified");
  99. if (type == RTC_INDEX_BUFFER) {
  100. curves.unmap(parent->numMappedBuffers);
  101. }
  102. else if (type >= RTC_VERTEX_BUFFER0 && type < RTCBufferType(RTC_VERTEX_BUFFER0 + numTimeSteps)) {
  103. vertices[type - RTC_VERTEX_BUFFER0].unmap(parent->numMappedBuffers);
  104. }
  105. else {
  106. throw_RTCError(RTC_INVALID_ARGUMENT,"unknown buffer type");
  107. }
  108. }
  109. void NativeCurves::setTessellationRate(float N)
  110. {
  111. if (parent->isStatic() && parent->isBuild())
  112. throw_RTCError(RTC_INVALID_OPERATION,"static geometries cannot get modified");
  113. tessellationRate = clamp((int)N,1,16);
  114. }
  115. void NativeCurves::immutable ()
  116. {
  117. const bool freeIndices = !parent->needBezierIndices;
  118. const bool freeVertices = !parent->needBezierVertices;
  119. if (freeIndices) curves.free();
  120. if (freeVertices )
  121. for (auto& buffer : vertices)
  122. buffer.free();
  123. }
  124. bool NativeCurves::verify ()
  125. {
  126. /*! verify consistent size of vertex arrays */
  127. if (vertices.size() == 0) return false;
  128. for (const auto& buffer : vertices)
  129. if (vertices[0].size() != buffer.size())
  130. return false;
  131. /*! verify indices */
  132. for (size_t i=0; i<numPrimitives; i++) {
  133. if (curves[i]+3 >= numVertices()) return false;
  134. }
  135. /*! verify vertices */
  136. for (const auto& buffer : vertices) {
  137. for (size_t i=0; i<buffer.size(); i++) {
  138. if (!isvalid(buffer[i].x)) return false;
  139. if (!isvalid(buffer[i].y)) return false;
  140. if (!isvalid(buffer[i].z)) return false;
  141. if (!isvalid(buffer[i].w)) return false;
  142. }
  143. }
  144. return true;
  145. }
  146. void NativeCurves::preCommit()
  147. {
  148. if (!isEnabled()) return;
  149. native_curves = (BufferRefT<unsigned>) curves;
  150. if (native_vertices.size() != vertices.size())
  151. native_vertices.resize(vertices.size());
  152. native_vertices0 = vertices[0];
  153. for (size_t i=0; i<vertices.size(); i++)
  154. native_vertices[i] = (BufferRefT<Vec3fa>) vertices[i];
  155. }
  156. template<typename Curve>
  157. void NativeCurves::interpolate_helper(unsigned primID, float u, float v, RTCBufferType buffer,
  158. float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv, size_t numFloats)
  159. {
  160. /* test if interpolation is enabled */
  161. #if defined(DEBUG)
  162. if ((parent->aflags & RTC_INTERPOLATE) == 0)
  163. throw_RTCError(RTC_INVALID_OPERATION,"rtcInterpolate can only get called when RTC_INTERPOLATE is enabled for the scene");
  164. #endif
  165. /* calculate base pointer and stride */
  166. assert((buffer >= RTC_VERTEX_BUFFER0 && buffer < RTCBufferType(RTC_VERTEX_BUFFER0 + numTimeSteps)) ||
  167. (buffer >= RTC_USER_VERTEX_BUFFER0 && buffer <= RTC_USER_VERTEX_BUFFER1));
  168. const char* src = nullptr;
  169. size_t stride = 0;
  170. if (buffer >= RTC_USER_VERTEX_BUFFER0) {
  171. src = userbuffers[buffer&0xFFFF].getPtr();
  172. stride = userbuffers[buffer&0xFFFF].getStride();
  173. } else {
  174. src = vertices[buffer&0xFFFF].getPtr();
  175. stride = vertices[buffer&0xFFFF].getStride();
  176. }
  177. for (size_t i=0; i<numFloats; i+=VSIZEX)
  178. {
  179. size_t ofs = i*sizeof(float);
  180. const size_t curve = curves[primID];
  181. const vboolx valid = vintx((int)i)+vintx(step) < vintx(numFloats);
  182. const vfloatx p0 = vfloatx::loadu(valid,(float*)&src[(curve+0)*stride+ofs]);
  183. const vfloatx p1 = vfloatx::loadu(valid,(float*)&src[(curve+1)*stride+ofs]);
  184. const vfloatx p2 = vfloatx::loadu(valid,(float*)&src[(curve+2)*stride+ofs]);
  185. const vfloatx p3 = vfloatx::loadu(valid,(float*)&src[(curve+3)*stride+ofs]);
  186. const Curve bezier(p0,p1,p2,p3);
  187. if (P ) vfloatx::storeu(valid,P+i, bezier.eval(u));
  188. if (dPdu ) vfloatx::storeu(valid,dPdu+i, bezier.eval_du(u));
  189. if (ddPdudu) vfloatx::storeu(valid,ddPdudu+i,bezier.eval_dudu(u));
  190. }
  191. }
  192. void NativeCurves::interpolate(unsigned primID, float u, float v, RTCBufferType buffer,
  193. float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv, size_t numFloats)
  194. {
  195. interpolate_helper<CurveT<vfloatx>>(primID,u,v,buffer,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,numFloats);
  196. }
  197. template<typename InputCurve3fa>
  198. void NativeCurves::commit_helper()
  199. {
  200. if (native_curves.size() != curves.size())
  201. {
  202. native_curves = APIBuffer<unsigned>(parent->device,curves.size(),sizeof(unsigned int),true);
  203. parallel_for(size_t(0), curves.size(), size_t(1024), [&] ( const range<size_t> r) {
  204. for (size_t i=r.begin(); i<r.end(); i++) {
  205. if (curves[i]+3 >= numVertices()) native_curves[i] = 0xFFFFFFF0; // invalid curves stay invalid this way
  206. else native_curves[i] = unsigned(4*i);
  207. }
  208. });
  209. }
  210. if (native_vertices.size() != vertices.size())
  211. native_vertices.resize(vertices.size());
  212. parallel_for(vertices.size(), [&] ( const size_t i ) {
  213. if (native_vertices[i].size() != 4*curves.size())
  214. native_vertices[i] = APIBuffer<Vec3fa>(parent->device,4*curves.size(),sizeof(Vec3fa),true);
  215. parallel_for(size_t(0), curves.size(), size_t(1024), [&] ( const range<size_t> rj ) {
  216. for (size_t j=rj.begin(); j<rj.end(); j++)
  217. {
  218. const unsigned id = curves[j];
  219. if (id+3 >= numVertices()) continue; // ignore invalid curves
  220. const Vec3fa v0 = vertices[i][id+0];
  221. const Vec3fa v1 = vertices[i][id+1];
  222. const Vec3fa v2 = vertices[i][id+2];
  223. const Vec3fa v3 = vertices[i][id+3];
  224. const InputCurve3fa icurve(v0,v1,v2,v3);
  225. Curve3fa ocurve; convert<Vec3fa>(icurve,ocurve);
  226. native_vertices[i].store(4*j+0,ocurve.v0);
  227. native_vertices[i].store(4*j+1,ocurve.v1);
  228. native_vertices[i].store(4*j+2,ocurve.v2);
  229. native_vertices[i].store(4*j+3,ocurve.v3);
  230. }
  231. });
  232. });
  233. native_vertices0 = native_vertices[0];
  234. }
  235. CurvesBezier::CurvesBezier (Scene* parent, SubType subtype, Basis basis, RTCGeometryFlags flags, size_t numPrimitives, size_t numVertices, size_t numTimeSteps)
  236. : NativeCurves(parent,subtype,basis,flags,numPrimitives,numVertices,numTimeSteps) {}
  237. void CurvesBezier::preCommit() {
  238. if (isEnabled()) commit_helper<BezierCurve3fa>();
  239. }
  240. void CurvesBezier::interpolate(unsigned primID, float u, float v, RTCBufferType buffer,
  241. float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv, size_t numFloats)
  242. {
  243. interpolate_helper<BezierCurveT<vfloatx>>(primID,u,v,buffer,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,numFloats);
  244. }
  245. CurvesBSpline::CurvesBSpline (Scene* parent, SubType subtype, Basis basis, RTCGeometryFlags flags, size_t numPrimitives, size_t numVertices, size_t numTimeSteps)
  246. : NativeCurves(parent,subtype,basis,flags,numPrimitives,numVertices,numTimeSteps) {}
  247. void CurvesBSpline::preCommit() {
  248. if (isEnabled()) commit_helper<BSplineCurve3fa>();
  249. }
  250. void CurvesBSpline::interpolate(unsigned primID, float u, float v, RTCBufferType buffer,
  251. float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv, size_t numFloats)
  252. {
  253. interpolate_helper<BSplineCurveT<vfloatx>>(primID,u,v,buffer,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,numFloats);
  254. }
  255. }