mirror of
				https://github.com/godotengine/godot.git
				synced 2025-11-04 07:31:16 +00:00 
			
		
		
		
	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.
		
			
				
	
	
		
			326 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			326 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// 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*);
 | 
						|
};
 |