Path: blob/master/thirdparty/embree/kernels/common/scene_subdiv_mesh.h
9905 views
// Copyright 2009-2021 Intel Corporation1// SPDX-License-Identifier: Apache-2.023#pragma once45#include "geometry.h"6#include "buffer.h"7#include "../subdiv/half_edge.h"8#include "../subdiv/tessellation_cache.h"9#include "../subdiv/catmullclark_coefficients.h"10#include "../subdiv/patch.h"1112namespace embree13{14struct HoleSet;15struct VertexCreaseMap;16struct EdgeCreaseMap;1718class SubdivMesh : public Geometry19{20ALIGNED_CLASS_(16);21public:2223typedef HalfEdge::Edge Edge;2425/*! type of this geometry */26static const Geometry::GTypeMask geom_type = Geometry::MTY_SUBDIV_MESH;2728/*! structure used to sort half edges using radix sort by their key */29struct KeyHalfEdge30{31KeyHalfEdge() {}3233KeyHalfEdge (uint64_t key, HalfEdge* edge)34: key(key), edge(edge) {}3536__forceinline operator uint64_t() const {37return key;38}3940friend __forceinline bool operator<(const KeyHalfEdge& e0, const KeyHalfEdge& e1) {41return e0.key < e1.key;42}4344public:45uint64_t key;46HalfEdge* edge;47};4849public:5051/*! subdiv mesh construction */52SubdivMesh(Device* device);53~SubdivMesh();5455public:56void setMask (unsigned mask);57void setSubdivisionMode (unsigned int topologyID, RTCSubdivisionMode mode);58void setVertexAttributeTopology(unsigned int vertexAttribID, unsigned int topologyID);59void setNumTimeSteps (unsigned int numTimeSteps);60void setVertexAttributeCount (unsigned int N);61void setTopologyCount (unsigned int N);62void setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num);63void* getBufferData(RTCBufferType type, unsigned int slot, BufferDataPointerType pointerType);64void updateBuffer(RTCBufferType type, unsigned int slot);65void setTessellationRate(float N);66bool verify();67void commit();68void addElementsToCount (GeometryCounts & counts) const;69void setDisplacementFunction (RTCDisplacementFunctionN func);70unsigned int getFirstHalfEdge(unsigned int faceID);71unsigned int getFace(unsigned int edgeID);72unsigned int getNextHalfEdge(unsigned int edgeID);73unsigned int getPreviousHalfEdge(unsigned int edgeID);74unsigned int getOppositeHalfEdge(unsigned int topologyID, unsigned int edgeID);7576public:7778/*! return the number of faces */79size_t numFaces() const {80return faceVertices.size();81}8283/*! return the number of edges */84size_t numEdges() const {85return topology[0].vertexIndices.size();86}8788/*! return the number of vertices */89size_t numVertices() const {90return vertices[0].size();91}9293/*! calculates the bounds of the i'th subdivision patch at the j'th timestep */94__forceinline BBox3fa bounds(size_t i, size_t j = 0) const {95return topology[0].getHalfEdge(i)->bounds(vertices[j]);96}9798/*! check if the i'th primitive is valid */99__forceinline bool valid(size_t i) const {100return topology[0].valid(i) && !invalidFace(i);101}102103/*! check if the i'th primitive is valid for the j'th time range */104__forceinline bool valid(size_t i, size_t j) const {105return topology[0].valid(i) && !invalidFace(i,j);106}107108/*! prints some statistics */109void printStatistics();110111/*! initializes the half edge data structure */112void initializeHalfEdgeStructures ();113114public:115116/*! returns the vertex buffer for some time step */117__forceinline const BufferView<Vec3fa>& getVertexBuffer( const size_t t = 0 ) const {118return vertices[t];119}120121/* returns tessellation level of edge */122__forceinline float getEdgeLevel(const size_t i) const123{124if (levels) return clamp(levels[i],1.0f,4096.0f); // FIXME: do we want to limit edge level?125else return clamp(tessellationRate,1.0f,4096.0f); // FIXME: do we want to limit edge level?126}127128public:129RTCDisplacementFunctionN displFunc; //!< displacement function130131/*! all buffers in this section are provided by the application */132public:133134/*! the topology contains all data that may differ when135* interpolating different user data buffers */136struct Topology137{138public:139140/*! Default topology construction */141Topology () : halfEdges(nullptr,0) {}142143/*! Topology initialization */144Topology (SubdivMesh* mesh);145146/*! make the class movable */147public:148Topology (Topology&& other) // FIXME: this is only required to workaround compilation issues under Windows149: mesh(std::move(other.mesh)),150vertexIndices(std::move(other.vertexIndices)),151subdiv_mode(std::move(other.subdiv_mode)),152halfEdges(std::move(other.halfEdges)),153halfEdges0(std::move(other.halfEdges0)),154halfEdges1(std::move(other.halfEdges1)) {}155156Topology& operator= (Topology&& other) // FIXME: this is only required to workaround compilation issues under Windows157{158mesh = std::move(other.mesh);159vertexIndices = std::move(other.vertexIndices);160subdiv_mode = std::move(other.subdiv_mode);161halfEdges = std::move(other.halfEdges);162halfEdges0 = std::move(other.halfEdges0);163halfEdges1 = std::move(other.halfEdges1);164return *this;165}166167public:168/*! check if the i'th primitive is valid in this topology */169__forceinline bool valid(size_t i) const170{171if (unlikely(subdiv_mode == RTC_SUBDIVISION_MODE_NO_BOUNDARY)) {172if (getHalfEdge(i)->faceHasBorder()) return false;173}174return true;175}176177/*! updates the interpolation mode for the topology */178void setSubdivisionMode (RTCSubdivisionMode mode);179180/*! marks all buffers as modified */181void update ();182183/*! verifies index array */184bool verify (size_t numVertices);185186/*! initializes the half edge data structure */187void initializeHalfEdgeStructures ();188189private:190191/*! recalculates the half edges */192void calculateHalfEdges();193194/*! updates half edges when recalculation is not necessary */195void updateHalfEdges();196197/*! user input data */198public:199200SubdivMesh* mesh;201202/*! indices of the vertices composing each face */203BufferView<unsigned int> vertexIndices;204205/*! subdiv interpolation mode */206RTCSubdivisionMode subdiv_mode;207208/*! generated data */209public:210211/*! returns the start half edge for face f */212__forceinline const HalfEdge* getHalfEdge ( const size_t f ) const {213return &halfEdges[mesh->faceStartEdge[f]];214}215216/*! Half edge structure, generated by initHalfEdgeStructures */217mvector<HalfEdge> halfEdges;218219/*! the following data is only required during construction of the220* half edge structure and can be cleared for static scenes */221private:222223/*! two arrays used to sort the half edges */224std::vector<KeyHalfEdge> halfEdges0;225std::vector<KeyHalfEdge> halfEdges1;226};227228/*! returns the start half edge for topology t and face f */229__forceinline const HalfEdge* getHalfEdge ( const size_t t , const size_t f ) const {230return topology[t].getHalfEdge(f);231}232233/*! buffer containing the number of vertices for each face */234BufferView<unsigned int> faceVertices;235236/*! array of topologies */237vector<Topology> topology;238239/*! vertex buffer (one buffer for each time step) */240vector<BufferView<Vec3fa>> vertices;241242/*! user data buffers */243vector<RawBufferView> vertexAttribs;244245/*! edge crease buffer containing edges (pairs of vertices) that carry edge crease weights */246BufferView<Edge> edge_creases;247248/*! edge crease weights for each edge of the edge_creases buffer */249BufferView<float> edge_crease_weights;250251/*! vertex crease buffer containing all vertices that carry vertex crease weights */252BufferView<unsigned int> vertex_creases;253254/*! vertex crease weights for each vertex of the vertex_creases buffer */255BufferView<float> vertex_crease_weights;256257/*! subdivision level for each half edge of the vertexIndices buffer */258BufferView<float> levels;259float tessellationRate; // constant rate that is used when levels is not set260261/*! buffer that marks specific faces as holes */262BufferView<unsigned> holes;263264/*! all data in this section is generated by initializeHalfEdgeStructures function */265private:266267/*! number of half edges used by faces */268size_t numHalfEdges;269270/*! fast lookup table to find the first half edge for some face */271mvector<uint32_t> faceStartEdge;272273/*! fast lookup table to find the face for some half edge */274mvector<uint32_t> halfEdgeFace;275276/*! set with all holes */277std::unique_ptr<HoleSet> holeSet;278279/*! fast lookup table to detect invalid faces */280mvector<char> invalid_face;281282/*! test if face i is invalid in timestep j */283__forceinline char& invalidFace(size_t i, size_t j = 0) { return invalid_face[i*numTimeSteps+j]; }284__forceinline const char& invalidFace(size_t i, size_t j = 0) const { return invalid_face[i*numTimeSteps+j]; }285286/*! interpolation cache */287public:288static __forceinline size_t numInterpolationSlots4(size_t stride) { return (stride+15)/16; }289static __forceinline size_t numInterpolationSlots8(size_t stride) { return (stride+31)/32; }290static __forceinline size_t interpolationSlot(size_t prim, size_t slot, size_t stride) {291const size_t slots = numInterpolationSlots4(stride);292assert(slot < slots);293return slots*prim+slot;294}295std::vector<std::vector<SharedLazyTessellationCache::CacheEntry>> vertex_buffer_tags;296std::vector<std::vector<SharedLazyTessellationCache::CacheEntry>> vertex_attrib_buffer_tags;297std::vector<Patch3fa::Ref> patch_eval_trees;298299/*! the following data is only required during construction of the300* half edge structure and can be cleared for static scenes */301private:302303/*! map with all vertex creases */304std::unique_ptr<VertexCreaseMap> vertexCreaseMap;305306/*! map with all edge creases */307std::unique_ptr<EdgeCreaseMap> edgeCreaseMap;308309protected:310311/*! counts number of geometry commits */312size_t commitCounter;313};314315namespace isa316{317struct SubdivMeshISA : public SubdivMesh318{319SubdivMeshISA (Device* device)320: SubdivMesh(device) {}321322void interpolate(const RTCInterpolateArguments* const args);323void interpolateN(const RTCInterpolateNArguments* const args);324};325}326327DECLARE_ISA_FUNCTION(SubdivMesh*, createSubdivMesh, Device*);328};329330331