scene_subdiv_mesh.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  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 "geometry.h"
  18. #include "buffer.h"
  19. #include "../subdiv/half_edge.h"
  20. #include "../subdiv/tessellation_cache.h"
  21. #include "../subdiv/catmullclark_coefficients.h"
  22. #include "../subdiv/patch.h"
  23. #include "../../common/algorithms/parallel_map.h"
  24. #include "../../common/algorithms/parallel_set.h"
  25. namespace embree
  26. {
  27. class SubdivMesh : public Geometry
  28. {
  29. ALIGNED_CLASS;
  30. public:
  31. typedef HalfEdge::Edge Edge;
  32. /*! type of this geometry */
  33. static const Geometry::Type geom_type = Geometry::SUBDIV_MESH;
  34. /*! structure used to sort half edges using radix sort by their key */
  35. struct KeyHalfEdge
  36. {
  37. KeyHalfEdge() {}
  38. KeyHalfEdge (uint64_t key, HalfEdge* edge)
  39. : key(key), edge(edge) {}
  40. __forceinline operator uint64_t() const {
  41. return key;
  42. }
  43. friend __forceinline bool operator<(const KeyHalfEdge& e0, const KeyHalfEdge& e1) {
  44. return e0.key < e1.key;
  45. }
  46. public:
  47. uint64_t key;
  48. HalfEdge* edge;
  49. };
  50. public:
  51. /*! subdiv mesh construction */
  52. SubdivMesh(Scene* parent, RTCGeometryFlags flags, size_t numFaces, size_t numEdges, size_t numVertices,
  53. size_t numCreases, size_t numCorners, size_t numHoles, size_t numTimeSteps);
  54. public:
  55. void enabling();
  56. void disabling();
  57. void setMask (unsigned mask);
  58. void setSubdivisionMode (unsigned topologyID, RTCSubdivisionMode mode);
  59. void setIndexBuffer(RTCBufferType vertexBuffer, RTCBufferType indexBuffer);
  60. void setBuffer(RTCBufferType type, void* ptr, size_t offset, size_t stride, size_t size);
  61. void* map(RTCBufferType type);
  62. void unmap(RTCBufferType type);
  63. void update ();
  64. void updateBuffer (RTCBufferType type);
  65. void setTessellationRate(float N);
  66. void immutable ();
  67. bool verify ();
  68. void setDisplacementFunction (RTCDisplacementFunc func, RTCBounds* bounds);
  69. void setDisplacementFunction2 (RTCDisplacementFunc2 func, RTCBounds* bounds);
  70. 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);
  71. void interpolateN(const void* valid_i, const unsigned* primIDs, const float* u, const float* v, size_t numUVs,
  72. RTCBufferType buffer, float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv, size_t numFloats);
  73. public:
  74. /*! return the number of faces */
  75. size_t size() const {
  76. return faceVertices.size();
  77. }
  78. /*! return the number of faces */
  79. size_t numFaces() const {
  80. return faceVertices.size();
  81. }
  82. /*! return the number of edges */
  83. size_t numEdges() const {
  84. return topology[0].vertexIndices.size();
  85. }
  86. /*! return the number of vertices */
  87. size_t numVertices() const {
  88. return vertices[0].size();
  89. }
  90. /*! calculates the bounds of the i'th subdivision patch at the j'th timestep */
  91. __forceinline BBox3fa bounds(size_t i, size_t j = 0) const {
  92. return topology[0].getHalfEdge(i)->bounds(vertices[j]);
  93. }
  94. /*! check if the i'th primitive is valid */
  95. __forceinline bool valid(size_t i) const {
  96. return topology[0].valid(i) && !invalidFace(i);
  97. }
  98. /*! check if the i'th primitive is valid for the j'th time range */
  99. __forceinline bool valid(size_t i, size_t j) const {
  100. return topology[0].valid(i) && !invalidFace(i,j);
  101. }
  102. /*! prints some statistics */
  103. void printStatistics();
  104. /*! initializes the half edge data structure */
  105. void initializeHalfEdgeStructures ();
  106. public:
  107. /*! returns the vertex buffer for some time step */
  108. __forceinline const BufferRefT<Vec3fa>& getVertexBuffer( const size_t t = 0 ) const {
  109. return vertices[t];
  110. }
  111. /* returns tessellation level of edge */
  112. __forceinline float getEdgeLevel(const size_t i) const
  113. {
  114. if (levels) return clamp(levels[i],1.0f,4096.0f); // FIXME: do we want to limit edge level?
  115. else return clamp(tessellationRate,1.0f,4096.0f); // FIXME: do we want to limit edge level?
  116. }
  117. public:
  118. RTCDisplacementFunc displFunc; //!< displacement function
  119. RTCDisplacementFunc2 displFunc2; //!< displacement function
  120. BBox3fa displBounds; //!< bounds for maximal displacement
  121. /*! all buffers in this section are provided by the application */
  122. public:
  123. /*! the topology contains all data that may differ when
  124. * interpolating different user data buffers */
  125. struct Topology
  126. {
  127. public:
  128. /*! Default topology construction */
  129. Topology () : halfEdges(nullptr) {}
  130. /*! Topology initialization */
  131. Topology (SubdivMesh* mesh, size_t numEdges);
  132. /*! make the class movable */
  133. public:
  134. Topology (Topology&& other) // FIXME: this is only required to workaround compilation issues under Windows
  135. : mesh(std::move(other.mesh)),
  136. vertexIndices(std::move(other.vertexIndices)),
  137. subdiv_mode(std::move(other.subdiv_mode)),
  138. halfEdges(std::move(other.halfEdges)),
  139. halfEdges0(std::move(other.halfEdges0)),
  140. halfEdges1(std::move(other.halfEdges1)) {}
  141. Topology& operator= (Topology&& other) // FIXME: this is only required to workaround compilation issues under Windows
  142. {
  143. mesh = std::move(other.mesh);
  144. vertexIndices = std::move(other.vertexIndices);
  145. subdiv_mode = std::move(other.subdiv_mode);
  146. halfEdges = std::move(other.halfEdges);
  147. halfEdges0 = std::move(other.halfEdges0);
  148. halfEdges1 = std::move(other.halfEdges1);
  149. return *this;
  150. }
  151. public:
  152. /*! check if the i'th primitive is valid in this topology */
  153. __forceinline bool valid(size_t i) const
  154. {
  155. if (unlikely(subdiv_mode == RTC_SUBDIV_NO_BOUNDARY)) {
  156. if (getHalfEdge(i)->faceHasBorder()) return false;
  157. }
  158. return true;
  159. }
  160. /*! updates the interpolation mode for the topology */
  161. void setSubdivisionMode (RTCSubdivisionMode mode);
  162. /*! marks all buffers as modified */
  163. void update ();
  164. /*! frees unused buffers */
  165. void immutable();
  166. /*! verifies index array */
  167. bool verify (size_t numVertices);
  168. /*! initializes the half edge data structure */
  169. void initializeHalfEdgeStructures ();
  170. private:
  171. /*! recalculates the half edges */
  172. void calculateHalfEdges();
  173. /*! updates half edges when recalculation is not necessary */
  174. void updateHalfEdges();
  175. /*! user input data */
  176. public:
  177. SubdivMesh* mesh;
  178. /*! indices of the vertices composing each face */
  179. APIBuffer<unsigned> vertexIndices;
  180. /*! subdiv interpolation mode */
  181. RTCSubdivisionMode subdiv_mode;
  182. /*! generated data */
  183. public:
  184. /*! returns the start half edge for face f */
  185. __forceinline const HalfEdge* getHalfEdge ( const size_t f ) const {
  186. return &halfEdges[mesh->faceStartEdge[f]];
  187. }
  188. /*! Half edge structure, generated by initHalfEdgeStructures */
  189. mvector<HalfEdge> halfEdges;
  190. /*! the following data is only required during construction of the
  191. * half edge structure and can be cleared for static scenes */
  192. private:
  193. /*! two arrays used to sort the half edges */
  194. std::vector<KeyHalfEdge> halfEdges0;
  195. std::vector<KeyHalfEdge> halfEdges1;
  196. };
  197. /*! returns the start half edge for topology t and face f */
  198. __forceinline const HalfEdge* getHalfEdge ( const size_t t , const size_t f ) const {
  199. return topology[t].getHalfEdge(f);
  200. }
  201. /*! buffer containing the number of vertices for each face */
  202. APIBuffer<unsigned> faceVertices;
  203. /*! array of topologies */
  204. vector<Topology> topology;
  205. /*! vertex buffer (one buffer for each time step) */
  206. vector<APIBuffer<Vec3fa>> vertices;
  207. /*! user data buffers */
  208. vector<APIBuffer<char>> userbuffers;
  209. /*! edge crease buffer containing edges (pairs of vertices) that carry edge crease weights */
  210. APIBuffer<Edge> edge_creases;
  211. /*! edge crease weights for each edge of the edge_creases buffer */
  212. APIBuffer<float> edge_crease_weights;
  213. /*! vertex crease buffer containing all vertices that carry vertex crease weights */
  214. APIBuffer<unsigned> vertex_creases;
  215. /*! vertex crease weights for each vertex of the vertex_creases buffer */
  216. APIBuffer<float> vertex_crease_weights;
  217. /*! subdivision level for each half edge of the vertexIndices buffer */
  218. APIBuffer<float> levels;
  219. float tessellationRate; // constant rate that is used when levels is not set
  220. /*! buffer that marks specific faces as holes */
  221. APIBuffer<unsigned> holes;
  222. /*! all data in this section is generated by initializeHalfEdgeStructures function */
  223. private:
  224. /*! number of half edges used by faces */
  225. size_t numHalfEdges;
  226. /*! fast lookup table to find the first half edge for some face */
  227. mvector<uint32_t> faceStartEdge;
  228. /*! set with all holes */
  229. parallel_set<uint32_t> holeSet;
  230. /*! fast lookup table to detect invalid faces */
  231. mvector<char> invalid_face;
  232. /*! test if face i is invalid in timestep j */
  233. __forceinline char& invalidFace(size_t i, size_t j = 0) { return invalid_face[i*numTimeSteps+j]; }
  234. __forceinline const char& invalidFace(size_t i, size_t j = 0) const { return invalid_face[i*numTimeSteps+j]; }
  235. /*! interpolation cache */
  236. public:
  237. static __forceinline size_t numInterpolationSlots4(size_t stride) { return (stride+15)/16; }
  238. static __forceinline size_t numInterpolationSlots8(size_t stride) { return (stride+31)/32; }
  239. static __forceinline size_t interpolationSlot(size_t prim, size_t slot, size_t stride) {
  240. #if defined (__AVX__)
  241. const size_t slots = numInterpolationSlots8(stride);
  242. #else
  243. const size_t slots = numInterpolationSlots4(stride);
  244. #endif
  245. assert(slot < slots);
  246. return slots*prim+slot;
  247. }
  248. std::vector<std::vector<SharedLazyTessellationCache::CacheEntry>> vertex_buffer_tags;
  249. std::vector<std::vector<SharedLazyTessellationCache::CacheEntry>> user_buffer_tags;
  250. std::vector<Patch3fa::Ref> patch_eval_trees;
  251. /*! the following data is only required during construction of the
  252. * half edge structure and can be cleared for static scenes */
  253. private:
  254. /*! map with all vertex creases */
  255. parallel_map<uint32_t,float> vertexCreaseMap;
  256. /*! map with all edge creases */
  257. parallel_map<uint64_t,float> edgeCreaseMap;
  258. };
  259. class SubdivMeshAVX : public SubdivMesh
  260. {
  261. public:
  262. //using SubdivMesh::SubdivMesh; // inherit all constructors // FIXME: compiler bug under VS2013
  263. SubdivMeshAVX (Scene* parent, RTCGeometryFlags flags, size_t numFaces, size_t numEdges, size_t numVertices,
  264. size_t numCreases, size_t numCorners, size_t numHoles, size_t numTimeSteps);
  265. 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);
  266. void interpolateN(const void* valid_i, const unsigned* primIDs, const float* u, const float* v, size_t numUVs,
  267. RTCBufferType buffer, float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv, size_t numFloats);
  268. template<typename vbool, typename vint, typename vfloat>
  269. void interpolateHelper(const vbool& valid1, const vint& primID, const vfloat& uu, const vfloat& vv, size_t numUVs,
  270. RTCBufferType buffer, float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv, size_t numFloats);
  271. };
  272. };