summaryrefslogtreecommitdiff
path: root/thirdparty/embree/kernels/common/scene_subdiv_mesh.h
diff options
context:
space:
mode:
authorjfons <joan.fonssanchez@gmail.com>2021-05-20 12:49:33 +0200
committerjfons <joan.fonssanchez@gmail.com>2021-05-21 17:00:24 +0200
commit767e374dced69b45db0afb30ca2ccf0bbbeef672 (patch)
treea712cecc2c8cc2c6d6ecdc4a50020d423ddb4c0c /thirdparty/embree/kernels/common/scene_subdiv_mesh.h
parent42b6602f1d4b108cecb94b94c0d2b645acaebd4f (diff)
Upgrade Embree to the latest official release.
Since Embree v3.13.0 supports AARCH64, switch back to the official repo instead of using Embree-aarch64. `thirdparty/embree/patches/godot-changes.patch` should now contain an accurate diff of the changes done to the library.
Diffstat (limited to 'thirdparty/embree/kernels/common/scene_subdiv_mesh.h')
-rw-r--r--thirdparty/embree/kernels/common/scene_subdiv_mesh.h326
1 files changed, 326 insertions, 0 deletions
diff --git a/thirdparty/embree/kernels/common/scene_subdiv_mesh.h b/thirdparty/embree/kernels/common/scene_subdiv_mesh.h
new file mode 100644
index 0000000000..1db170196d
--- /dev/null
+++ b/thirdparty/embree/kernels/common/scene_subdiv_mesh.h
@@ -0,0 +1,326 @@
+// Copyright 2009-2021 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "geometry.h"
+#include "buffer.h"
+#include "../subdiv/half_edge.h"
+#include "../subdiv/tessellation_cache.h"
+#include "../subdiv/catmullclark_coefficients.h"
+#include "../subdiv/patch.h"
+#include "../../common/algorithms/parallel_map.h"
+#include "../../common/algorithms/parallel_set.h"
+
+namespace embree
+{
+ class SubdivMesh : public Geometry
+ {
+ ALIGNED_CLASS_(16);
+ public:
+
+ typedef HalfEdge::Edge Edge;
+
+ /*! type of this geometry */
+ static const Geometry::GTypeMask geom_type = Geometry::MTY_SUBDIV_MESH;
+
+ /*! structure used to sort half edges using radix sort by their key */
+ struct KeyHalfEdge
+ {
+ KeyHalfEdge() {}
+
+ KeyHalfEdge (uint64_t key, HalfEdge* edge)
+ : key(key), edge(edge) {}
+
+ __forceinline operator uint64_t() const {
+ return key;
+ }
+
+ friend __forceinline bool operator<(const KeyHalfEdge& e0, const KeyHalfEdge& e1) {
+ return e0.key < e1.key;
+ }
+
+ public:
+ uint64_t key;
+ HalfEdge* edge;
+ };
+
+ public:
+
+ /*! subdiv mesh construction */
+ SubdivMesh(Device* device);
+
+ public:
+ void setMask (unsigned mask);
+ void setSubdivisionMode (unsigned int topologyID, RTCSubdivisionMode mode);
+ void setVertexAttributeTopology(unsigned int vertexAttribID, unsigned int topologyID);
+ void setNumTimeSteps (unsigned int numTimeSteps);
+ void setVertexAttributeCount (unsigned int N);
+ void setTopologyCount (unsigned int N);
+ void setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num);
+ void* getBuffer(RTCBufferType type, unsigned int slot);
+ void updateBuffer(RTCBufferType type, unsigned int slot);
+ void setTessellationRate(float N);
+ bool verify();
+ void commit();
+ void addElementsToCount (GeometryCounts & counts) const;
+ void setDisplacementFunction (RTCDisplacementFunctionN func);
+ unsigned int getFirstHalfEdge(unsigned int faceID);
+ unsigned int getFace(unsigned int edgeID);
+ unsigned int getNextHalfEdge(unsigned int edgeID);
+ unsigned int getPreviousHalfEdge(unsigned int edgeID);
+ unsigned int getOppositeHalfEdge(unsigned int topologyID, unsigned int edgeID);
+
+ public:
+
+ /*! return the number of faces */
+ size_t numFaces() const {
+ return faceVertices.size();
+ }
+
+ /*! return the number of edges */
+ size_t numEdges() const {
+ return topology[0].vertexIndices.size();
+ }
+
+ /*! return the number of vertices */
+ size_t numVertices() const {
+ return vertices[0].size();
+ }
+
+ /*! calculates the bounds of the i'th subdivision patch at the j'th timestep */
+ __forceinline BBox3fa bounds(size_t i, size_t j = 0) const {
+ return topology[0].getHalfEdge(i)->bounds(vertices[j]);
+ }
+
+ /*! check if the i'th primitive is valid */
+ __forceinline bool valid(size_t i) const {
+ return topology[0].valid(i) && !invalidFace(i);
+ }
+
+ /*! check if the i'th primitive is valid for the j'th time range */
+ __forceinline bool valid(size_t i, size_t j) const {
+ return topology[0].valid(i) && !invalidFace(i,j);
+ }
+
+ /*! prints some statistics */
+ void printStatistics();
+
+ /*! initializes the half edge data structure */
+ void initializeHalfEdgeStructures ();
+
+ public:
+
+ /*! returns the vertex buffer for some time step */
+ __forceinline const BufferView<Vec3fa>& getVertexBuffer( const size_t t = 0 ) const {
+ return vertices[t];
+ }
+
+ /* returns tessellation level of edge */
+ __forceinline float getEdgeLevel(const size_t i) const
+ {
+ if (levels) return clamp(levels[i],1.0f,4096.0f); // FIXME: do we want to limit edge level?
+ else return clamp(tessellationRate,1.0f,4096.0f); // FIXME: do we want to limit edge level?
+ }
+
+ public:
+ RTCDisplacementFunctionN displFunc; //!< displacement function
+
+ /*! all buffers in this section are provided by the application */
+ public:
+
+ /*! the topology contains all data that may differ when
+ * interpolating different user data buffers */
+ struct Topology
+ {
+ public:
+
+ /*! Default topology construction */
+ Topology () : halfEdges(nullptr,0) {}
+
+ /*! Topology initialization */
+ Topology (SubdivMesh* mesh);
+
+ /*! make the class movable */
+ public:
+ Topology (Topology&& other) // FIXME: this is only required to workaround compilation issues under Windows
+ : mesh(std::move(other.mesh)),
+ vertexIndices(std::move(other.vertexIndices)),
+ subdiv_mode(std::move(other.subdiv_mode)),
+ halfEdges(std::move(other.halfEdges)),
+ halfEdges0(std::move(other.halfEdges0)),
+ halfEdges1(std::move(other.halfEdges1)) {}
+
+ Topology& operator= (Topology&& other) // FIXME: this is only required to workaround compilation issues under Windows
+ {
+ mesh = std::move(other.mesh);
+ vertexIndices = std::move(other.vertexIndices);
+ subdiv_mode = std::move(other.subdiv_mode);
+ halfEdges = std::move(other.halfEdges);
+ halfEdges0 = std::move(other.halfEdges0);
+ halfEdges1 = std::move(other.halfEdges1);
+ return *this;
+ }
+
+ public:
+ /*! check if the i'th primitive is valid in this topology */
+ __forceinline bool valid(size_t i) const
+ {
+ if (unlikely(subdiv_mode == RTC_SUBDIVISION_MODE_NO_BOUNDARY)) {
+ if (getHalfEdge(i)->faceHasBorder()) return false;
+ }
+ return true;
+ }
+
+ /*! updates the interpolation mode for the topology */
+ void setSubdivisionMode (RTCSubdivisionMode mode);
+
+ /*! marks all buffers as modified */
+ void update ();
+
+ /*! verifies index array */
+ bool verify (size_t numVertices);
+
+ /*! initializes the half edge data structure */
+ void initializeHalfEdgeStructures ();
+
+ private:
+
+ /*! recalculates the half edges */
+ void calculateHalfEdges();
+
+ /*! updates half edges when recalculation is not necessary */
+ void updateHalfEdges();
+
+ /*! user input data */
+ public:
+
+ SubdivMesh* mesh;
+
+ /*! indices of the vertices composing each face */
+ BufferView<unsigned int> vertexIndices;
+
+ /*! subdiv interpolation mode */
+ RTCSubdivisionMode subdiv_mode;
+
+ /*! generated data */
+ public:
+
+ /*! returns the start half edge for face f */
+ __forceinline const HalfEdge* getHalfEdge ( const size_t f ) const {
+ return &halfEdges[mesh->faceStartEdge[f]];
+ }
+
+ /*! Half edge structure, generated by initHalfEdgeStructures */
+ mvector<HalfEdge> halfEdges;
+
+ /*! the following data is only required during construction of the
+ * half edge structure and can be cleared for static scenes */
+ private:
+
+ /*! two arrays used to sort the half edges */
+ std::vector<KeyHalfEdge> halfEdges0;
+ std::vector<KeyHalfEdge> halfEdges1;
+ };
+
+ /*! returns the start half edge for topology t and face f */
+ __forceinline const HalfEdge* getHalfEdge ( const size_t t , const size_t f ) const {
+ return topology[t].getHalfEdge(f);
+ }
+
+ /*! buffer containing the number of vertices for each face */
+ BufferView<unsigned int> faceVertices;
+
+ /*! array of topologies */
+ vector<Topology> topology;
+
+ /*! vertex buffer (one buffer for each time step) */
+ vector<BufferView<Vec3fa>> vertices;
+
+ /*! user data buffers */
+ vector<RawBufferView> vertexAttribs;
+
+ /*! edge crease buffer containing edges (pairs of vertices) that carry edge crease weights */
+ BufferView<Edge> edge_creases;
+
+ /*! edge crease weights for each edge of the edge_creases buffer */
+ BufferView<float> edge_crease_weights;
+
+ /*! vertex crease buffer containing all vertices that carry vertex crease weights */
+ BufferView<unsigned int> vertex_creases;
+
+ /*! vertex crease weights for each vertex of the vertex_creases buffer */
+ BufferView<float> vertex_crease_weights;
+
+ /*! subdivision level for each half edge of the vertexIndices buffer */
+ BufferView<float> levels;
+ float tessellationRate; // constant rate that is used when levels is not set
+
+ /*! buffer that marks specific faces as holes */
+ BufferView<unsigned> holes;
+
+ /*! all data in this section is generated by initializeHalfEdgeStructures function */
+ private:
+
+ /*! number of half edges used by faces */
+ size_t numHalfEdges;
+
+ /*! fast lookup table to find the first half edge for some face */
+ mvector<uint32_t> faceStartEdge;
+
+ /*! fast lookup table to find the face for some half edge */
+ mvector<uint32_t> halfEdgeFace;
+
+ /*! set with all holes */
+ parallel_set<uint32_t> holeSet;
+
+ /*! fast lookup table to detect invalid faces */
+ mvector<char> invalid_face;
+
+ /*! test if face i is invalid in timestep j */
+ __forceinline char& invalidFace(size_t i, size_t j = 0) { return invalid_face[i*numTimeSteps+j]; }
+ __forceinline const char& invalidFace(size_t i, size_t j = 0) const { return invalid_face[i*numTimeSteps+j]; }
+
+ /*! interpolation cache */
+ public:
+ static __forceinline size_t numInterpolationSlots4(size_t stride) { return (stride+15)/16; }
+ static __forceinline size_t numInterpolationSlots8(size_t stride) { return (stride+31)/32; }
+ static __forceinline size_t interpolationSlot(size_t prim, size_t slot, size_t stride) {
+ const size_t slots = numInterpolationSlots4(stride);
+ assert(slot < slots);
+ return slots*prim+slot;
+ }
+ std::vector<std::vector<SharedLazyTessellationCache::CacheEntry>> vertex_buffer_tags;
+ std::vector<std::vector<SharedLazyTessellationCache::CacheEntry>> vertex_attrib_buffer_tags;
+ std::vector<Patch3fa::Ref> patch_eval_trees;
+
+ /*! the following data is only required during construction of the
+ * half edge structure and can be cleared for static scenes */
+ private:
+
+ /*! map with all vertex creases */
+ parallel_map<uint32_t,float> vertexCreaseMap;
+
+ /*! map with all edge creases */
+ parallel_map<uint64_t,float> edgeCreaseMap;
+
+ protected:
+
+ /*! counts number of geometry commits */
+ size_t commitCounter;
+ };
+
+ namespace isa
+ {
+ struct SubdivMeshISA : public SubdivMesh
+ {
+ SubdivMeshISA (Device* device)
+ : SubdivMesh(device) {}
+
+ void interpolate(const RTCInterpolateArguments* const args);
+ void interpolateN(const RTCInterpolateNArguments* const args);
+ };
+ }
+
+ DECLARE_ISA_FUNCTION(SubdivMesh*, createSubdivMesh, Device*);
+};