scene_subdiv_mesh.h 11 KB

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