scene_subdiv_mesh.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #include "geometry.h"
  5. #include "buffer.h"
  6. #include "../subdiv/half_edge.h"
  7. #include "../subdiv/tessellation_cache.h"
  8. #include "../subdiv/catmullclark_coefficients.h"
  9. #include "../subdiv/patch.h"
  10. #include "../../common/algorithms/parallel_map.h"
  11. #include "../../common/algorithms/parallel_set.h"
  12. namespace embree
  13. {
  14. class SubdivMesh : public Geometry
  15. {
  16. ALIGNED_CLASS_(16);
  17. public:
  18. typedef HalfEdge::Edge Edge;
  19. /*! type of this geometry */
  20. static const Geometry::GTypeMask geom_type = Geometry::MTY_SUBDIV_MESH;
  21. /*! structure used to sort half edges using radix sort by their key */
  22. struct KeyHalfEdge
  23. {
  24. KeyHalfEdge() {}
  25. KeyHalfEdge (uint64_t key, HalfEdge* edge)
  26. : key(key), edge(edge) {}
  27. __forceinline operator uint64_t() const {
  28. return key;
  29. }
  30. friend __forceinline bool operator<(const KeyHalfEdge& e0, const KeyHalfEdge& e1) {
  31. return e0.key < e1.key;
  32. }
  33. public:
  34. uint64_t key;
  35. HalfEdge* edge;
  36. };
  37. public:
  38. /*! subdiv mesh construction */
  39. SubdivMesh(Device* device);
  40. public:
  41. void setMask (unsigned mask);
  42. void setSubdivisionMode (unsigned int topologyID, RTCSubdivisionMode mode);
  43. void setVertexAttributeTopology(unsigned int vertexAttribID, unsigned int topologyID);
  44. void setNumTimeSteps (unsigned int numTimeSteps);
  45. void setVertexAttributeCount (unsigned int N);
  46. void setTopologyCount (unsigned int N);
  47. void setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num);
  48. void* getBuffer(RTCBufferType type, unsigned int slot);
  49. void updateBuffer(RTCBufferType type, unsigned int slot);
  50. void setTessellationRate(float N);
  51. bool verify();
  52. void commit();
  53. void addElementsToCount (GeometryCounts & counts) const;
  54. void setDisplacementFunction (RTCDisplacementFunctionN func);
  55. unsigned int getFirstHalfEdge(unsigned int faceID);
  56. unsigned int getFace(unsigned int edgeID);
  57. unsigned int getNextHalfEdge(unsigned int edgeID);
  58. unsigned int getPreviousHalfEdge(unsigned int edgeID);
  59. unsigned int getOppositeHalfEdge(unsigned int topologyID, unsigned int edgeID);
  60. public:
  61. /*! return the number of faces */
  62. size_t numFaces() const {
  63. return faceVertices.size();
  64. }
  65. /*! return the number of edges */
  66. size_t numEdges() const {
  67. return topology[0].vertexIndices.size();
  68. }
  69. /*! return the number of vertices */
  70. size_t numVertices() const {
  71. return vertices[0].size();
  72. }
  73. /*! calculates the bounds of the i'th subdivision patch at the j'th timestep */
  74. __forceinline BBox3fa bounds(size_t i, size_t j = 0) const {
  75. return topology[0].getHalfEdge(i)->bounds(vertices[j]);
  76. }
  77. /*! check if the i'th primitive is valid */
  78. __forceinline bool valid(size_t i) const {
  79. return topology[0].valid(i) && !invalidFace(i);
  80. }
  81. /*! check if the i'th primitive is valid for the j'th time range */
  82. __forceinline bool valid(size_t i, size_t j) const {
  83. return topology[0].valid(i) && !invalidFace(i,j);
  84. }
  85. /*! prints some statistics */
  86. void printStatistics();
  87. /*! initializes the half edge data structure */
  88. void initializeHalfEdgeStructures ();
  89. public:
  90. /*! returns the vertex buffer for some time step */
  91. __forceinline const BufferView<Vec3fa>& getVertexBuffer( const size_t t = 0 ) const {
  92. return vertices[t];
  93. }
  94. /* returns tessellation level of edge */
  95. __forceinline float getEdgeLevel(const size_t i) const
  96. {
  97. if (levels) return clamp(levels[i],1.0f,4096.0f); // FIXME: do we want to limit edge level?
  98. else return clamp(tessellationRate,1.0f,4096.0f); // FIXME: do we want to limit edge level?
  99. }
  100. public:
  101. RTCDisplacementFunctionN displFunc; //!< displacement function
  102. /*! all buffers in this section are provided by the application */
  103. public:
  104. /*! the topology contains all data that may differ when
  105. * interpolating different user data buffers */
  106. struct Topology
  107. {
  108. public:
  109. /*! Default topology construction */
  110. Topology () : halfEdges(nullptr,0) {}
  111. /*! Topology initialization */
  112. Topology (SubdivMesh* mesh);
  113. /*! make the class movable */
  114. public:
  115. Topology (Topology&& other) // FIXME: this is only required to workaround compilation issues under Windows
  116. : mesh(std::move(other.mesh)),
  117. vertexIndices(std::move(other.vertexIndices)),
  118. subdiv_mode(std::move(other.subdiv_mode)),
  119. halfEdges(std::move(other.halfEdges)),
  120. halfEdges0(std::move(other.halfEdges0)),
  121. halfEdges1(std::move(other.halfEdges1)) {}
  122. Topology& operator= (Topology&& other) // FIXME: this is only required to workaround compilation issues under Windows
  123. {
  124. mesh = std::move(other.mesh);
  125. vertexIndices = std::move(other.vertexIndices);
  126. subdiv_mode = std::move(other.subdiv_mode);
  127. halfEdges = std::move(other.halfEdges);
  128. halfEdges0 = std::move(other.halfEdges0);
  129. halfEdges1 = std::move(other.halfEdges1);
  130. return *this;
  131. }
  132. public:
  133. /*! check if the i'th primitive is valid in this topology */
  134. __forceinline bool valid(size_t i) const
  135. {
  136. if (unlikely(subdiv_mode == RTC_SUBDIVISION_MODE_NO_BOUNDARY)) {
  137. if (getHalfEdge(i)->faceHasBorder()) return false;
  138. }
  139. return true;
  140. }
  141. /*! updates the interpolation mode for the topology */
  142. void setSubdivisionMode (RTCSubdivisionMode mode);
  143. /*! marks all buffers as modified */
  144. void update ();
  145. /*! verifies index array */
  146. bool verify (size_t numVertices);
  147. /*! initializes the half edge data structure */
  148. void initializeHalfEdgeStructures ();
  149. private:
  150. /*! recalculates the half edges */
  151. void calculateHalfEdges();
  152. /*! updates half edges when recalculation is not necessary */
  153. void updateHalfEdges();
  154. /*! user input data */
  155. public:
  156. SubdivMesh* mesh;
  157. /*! indices of the vertices composing each face */
  158. BufferView<unsigned int> vertexIndices;
  159. /*! subdiv interpolation mode */
  160. RTCSubdivisionMode subdiv_mode;
  161. /*! generated data */
  162. public:
  163. /*! returns the start half edge for face f */
  164. __forceinline const HalfEdge* getHalfEdge ( const size_t f ) const {
  165. return &halfEdges[mesh->faceStartEdge[f]];
  166. }
  167. /*! Half edge structure, generated by initHalfEdgeStructures */
  168. mvector<HalfEdge> halfEdges;
  169. /*! the following data is only required during construction of the
  170. * half edge structure and can be cleared for static scenes */
  171. private:
  172. /*! two arrays used to sort the half edges */
  173. std::vector<KeyHalfEdge> halfEdges0;
  174. std::vector<KeyHalfEdge> halfEdges1;
  175. };
  176. /*! returns the start half edge for topology t and face f */
  177. __forceinline const HalfEdge* getHalfEdge ( const size_t t , const size_t f ) const {
  178. return topology[t].getHalfEdge(f);
  179. }
  180. /*! buffer containing the number of vertices for each face */
  181. BufferView<unsigned int> faceVertices;
  182. /*! array of topologies */
  183. vector<Topology> topology;
  184. /*! vertex buffer (one buffer for each time step) */
  185. vector<BufferView<Vec3fa>> vertices;
  186. /*! user data buffers */
  187. vector<RawBufferView> vertexAttribs;
  188. /*! edge crease buffer containing edges (pairs of vertices) that carry edge crease weights */
  189. BufferView<Edge> edge_creases;
  190. /*! edge crease weights for each edge of the edge_creases buffer */
  191. BufferView<float> edge_crease_weights;
  192. /*! vertex crease buffer containing all vertices that carry vertex crease weights */
  193. BufferView<unsigned int> vertex_creases;
  194. /*! vertex crease weights for each vertex of the vertex_creases buffer */
  195. BufferView<float> vertex_crease_weights;
  196. /*! subdivision level for each half edge of the vertexIndices buffer */
  197. BufferView<float> levels;
  198. float tessellationRate; // constant rate that is used when levels is not set
  199. /*! buffer that marks specific faces as holes */
  200. BufferView<unsigned> holes;
  201. /*! all data in this section is generated by initializeHalfEdgeStructures function */
  202. private:
  203. /*! number of half edges used by faces */
  204. size_t numHalfEdges;
  205. /*! fast lookup table to find the first half edge for some face */
  206. mvector<uint32_t> faceStartEdge;
  207. /*! fast lookup table to find the face for some half edge */
  208. mvector<uint32_t> halfEdgeFace;
  209. /*! set with all holes */
  210. parallel_set<uint32_t> holeSet;
  211. /*! fast lookup table to detect invalid faces */
  212. mvector<char> invalid_face;
  213. /*! test if face i is invalid in timestep j */
  214. __forceinline char& invalidFace(size_t i, size_t j = 0) { return invalid_face[i*numTimeSteps+j]; }
  215. __forceinline const char& invalidFace(size_t i, size_t j = 0) const { return invalid_face[i*numTimeSteps+j]; }
  216. /*! interpolation cache */
  217. public:
  218. static __forceinline size_t numInterpolationSlots4(size_t stride) { return (stride+15)/16; }
  219. static __forceinline size_t numInterpolationSlots8(size_t stride) { return (stride+31)/32; }
  220. static __forceinline size_t interpolationSlot(size_t prim, size_t slot, size_t stride) {
  221. const size_t slots = numInterpolationSlots4(stride);
  222. assert(slot < slots);
  223. return slots*prim+slot;
  224. }
  225. std::vector<std::vector<SharedLazyTessellationCache::CacheEntry>> vertex_buffer_tags;
  226. std::vector<std::vector<SharedLazyTessellationCache::CacheEntry>> vertex_attrib_buffer_tags;
  227. std::vector<Patch3fa::Ref> patch_eval_trees;
  228. /*! the following data is only required during construction of the
  229. * half edge structure and can be cleared for static scenes */
  230. private:
  231. /*! map with all vertex creases */
  232. parallel_map<uint32_t,float> vertexCreaseMap;
  233. /*! map with all edge creases */
  234. parallel_map<uint64_t,float> edgeCreaseMap;
  235. protected:
  236. /*! counts number of geometry commits */
  237. size_t commitCounter;
  238. };
  239. namespace isa
  240. {
  241. struct SubdivMeshISA : public SubdivMesh
  242. {
  243. SubdivMeshISA (Device* device)
  244. : SubdivMesh(device) {}
  245. void interpolate(const RTCInterpolateArguments* const args);
  246. void interpolateN(const RTCInterpolateNArguments* const args);
  247. };
  248. }
  249. DECLARE_ISA_FUNCTION(SubdivMesh*, createSubdivMesh, Device*);
  250. };