400 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			400 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright 2009-2021 Intel Corporation
 | |
| // SPDX-License-Identifier: Apache-2.0
 | |
|  
 | |
| #pragma once
 | |
| 
 | |
| #include "default.h"
 | |
| #include "device.h"
 | |
| #include "builder.h"
 | |
| #include "scene_triangle_mesh.h"
 | |
| #include "scene_quad_mesh.h"
 | |
| #include "scene_user_geometry.h"
 | |
| #include "scene_instance.h"
 | |
| #include "scene_instance_array.h"
 | |
| #include "scene_curves.h"
 | |
| #include "scene_line_segments.h"
 | |
| #include "scene_subdiv_mesh.h"
 | |
| #include "scene_grid_mesh.h"
 | |
| #include "scene_points.h"
 | |
| #include "../subdiv/tessellation_cache.h"
 | |
| 
 | |
| #include "acceln.h"
 | |
| #include "geometry.h"
 | |
| 
 | |
| #if defined(EMBREE_SYCL_SUPPORT)
 | |
| #include "../sycl/rthwif_embree_builder.h"
 | |
| #endif
 | |
| 
 | |
| namespace embree
 | |
| {
 | |
|   struct TaskGroup;
 | |
| 
 | |
|   /*! Base class all scenes are derived from */
 | |
|   class Scene : public AccelN
 | |
|   {
 | |
|     ALIGNED_CLASS_USM_(std::alignment_of<Scene>::value);
 | |
| 
 | |
|   public:
 | |
|     template<typename Ty, bool mblur = false>
 | |
|       class Iterator
 | |
|       {
 | |
|       public:
 | |
|       Iterator ()  {}
 | |
|       
 | |
|       Iterator (Scene* scene, bool all = false) 
 | |
|       : scene(scene), all(all) {}
 | |
|       
 | |
|       __forceinline Ty* at(const size_t i)
 | |
|       {
 | |
|         Geometry* geom = scene->geometries[i].ptr;
 | |
|         if (geom == nullptr) return nullptr;
 | |
|         if (!all && !geom->isEnabled()) return nullptr;
 | |
|         const size_t mask = geom->getTypeMask() & Ty::geom_type; 
 | |
|         if (!(mask)) return nullptr;
 | |
|         if ((geom->numTimeSteps != 1) != mblur) return nullptr;
 | |
|         return (Ty*) geom;
 | |
|       }
 | |
| 
 | |
|       __forceinline Ty* operator[] (const size_t i) {
 | |
|         return at(i);
 | |
|       }
 | |
| 
 | |
|       __forceinline size_t size() const {
 | |
|         return scene->size();
 | |
|       }
 | |
|       
 | |
|       __forceinline size_t numPrimitives() const {
 | |
|         return scene->getNumPrimitives(Ty::geom_type,mblur);
 | |
|       }
 | |
| 
 | |
|       __forceinline size_t maxPrimitivesPerGeometry() 
 | |
|       {
 | |
|         size_t ret = 0;
 | |
|         for (size_t i=0; i<scene->size(); i++) {
 | |
|           Ty* mesh = at(i);
 | |
|           if (mesh == nullptr) continue;
 | |
|           ret = max(ret,mesh->size());
 | |
|         }
 | |
|         return ret;
 | |
|       }
 | |
| 
 | |
|       __forceinline unsigned int maxGeomID() 
 | |
|       {
 | |
|         unsigned int ret = 0;
 | |
|         for (size_t i=0; i<scene->size(); i++) {
 | |
|           Ty* mesh = at(i);
 | |
|           if (mesh == nullptr) continue;
 | |
|           ret = max(ret,(unsigned int)i);
 | |
|         }
 | |
|         return ret;
 | |
|       }
 | |
| 
 | |
|       __forceinline unsigned maxTimeStepsPerGeometry()
 | |
|       {
 | |
|         unsigned ret = 0;
 | |
|         for (size_t i=0; i<scene->size(); i++) {
 | |
|           Ty* mesh = at(i);
 | |
|           if (mesh == nullptr) continue;
 | |
|           ret = max(ret,mesh->numTimeSteps);
 | |
|         }
 | |
|         return ret;
 | |
|       }
 | |
|       
 | |
|     private:
 | |
|       Scene* scene;
 | |
|       bool all;
 | |
|       };
 | |
| 
 | |
|       class Iterator2
 | |
|       {
 | |
|       public:
 | |
|       Iterator2 () {}
 | |
|       
 | |
|       Iterator2 (Scene* scene, Geometry::GTypeMask typemask, bool mblur) 
 | |
|       : scene(scene), typemask(typemask), mblur(mblur) {}
 | |
|       
 | |
|       __forceinline Geometry* at(const size_t i)
 | |
|       {
 | |
|         Geometry* geom = scene->geometries[i].ptr;
 | |
|         if (geom == nullptr) return nullptr;
 | |
|         if (!geom->isEnabled()) return nullptr;
 | |
|         if (!(geom->getTypeMask() & typemask)) return nullptr;
 | |
|         if ((geom->numTimeSteps != 1) != mblur) return nullptr;
 | |
|         return geom;
 | |
|       }
 | |
| 
 | |
|       __forceinline Geometry* operator[] (const size_t i) {
 | |
|         return at(i);
 | |
|       }
 | |
| 
 | |
|       __forceinline size_t size() const {
 | |
|         return scene->size();
 | |
|       }
 | |
|       
 | |
|     private:
 | |
|       Scene* scene;
 | |
|       Geometry::GTypeMask typemask;
 | |
|       bool mblur;
 | |
|     };
 | |
| 
 | |
|   public:
 | |
|     
 | |
|     /*! Scene construction */
 | |
|     Scene (Device* device);
 | |
| 
 | |
|     /*! Scene destruction */
 | |
|     ~Scene () noexcept;
 | |
| 
 | |
|   private:
 | |
|     
 | |
|     /*! class is non-copyable */
 | |
|     Scene (const Scene& other) DELETED; // do not implement
 | |
|     Scene& operator= (const Scene& other) DELETED; // do not implement
 | |
| 
 | |
|   public:
 | |
|     void createTriangleAccel();
 | |
|     void createTriangleMBAccel();
 | |
|     void createQuadAccel();
 | |
|     void createQuadMBAccel();
 | |
|     void createHairAccel();
 | |
|     void createHairMBAccel();
 | |
|     void createSubdivAccel();
 | |
|     void createSubdivMBAccel();
 | |
|     void createUserGeometryAccel();
 | |
|     void createUserGeometryMBAccel();
 | |
|     void createInstanceAccel();
 | |
|     void createInstanceMBAccel();
 | |
|     void createInstanceExpensiveAccel();
 | |
|     void createInstanceExpensiveMBAccel();
 | |
|     void createInstanceArrayAccel();
 | |
|     void createInstanceArrayMBAccel();
 | |
|     void createGridAccel();
 | |
|     void createGridMBAccel();
 | |
| 
 | |
|     /*! prints statistics about the scene */
 | |
|     void printStatistics();
 | |
| 
 | |
|     /*! clears the scene */
 | |
|     void clear();
 | |
| 
 | |
|     /*! detaches some geometry */
 | |
|     void detachGeometry(size_t geomID);
 | |
| 
 | |
|     void setBuildQuality(RTCBuildQuality quality_flags);
 | |
|     RTCBuildQuality getBuildQuality() const;
 | |
|     
 | |
|     void setSceneFlags(RTCSceneFlags scene_flags);
 | |
|     RTCSceneFlags getSceneFlags() const;
 | |
| 
 | |
|     void build_cpu_accels();
 | |
|     void build_gpu_accels();
 | |
|     void commit (bool join);
 | |
|     void commit_task ();
 | |
|     void build () {}
 | |
| 
 | |
|     /* return number of geometries */
 | |
|     __forceinline size_t size() const { return geometries.size(); }
 | |
|     
 | |
|     /* bind geometry to the scene */
 | |
|     unsigned int bind (unsigned geomID, Ref<Geometry> geometry);
 | |
|     
 | |
|     /* determines if scene is modified */
 | |
|     __forceinline bool isModified() const { return modified; }
 | |
| 
 | |
|     /* sets modified flag */
 | |
|     __forceinline void setModified(bool f = true) { 
 | |
|       modified = f; 
 | |
|     }
 | |
| 
 | |
|     __forceinline bool isGeometryModified(size_t geomID)
 | |
|     {
 | |
|       Ref<Geometry>& g = geometries[geomID];
 | |
|       if (!g) return false;
 | |
|       return g->getModCounter() > geometryModCounters_[geomID];
 | |
|     }
 | |
| 
 | |
|   protected:
 | |
| 
 | |
|     void checkIfModifiedAndSet ();
 | |
| 
 | |
|   public:
 | |
| 
 | |
|     /* get mesh by ID */
 | |
|     __forceinline       Geometry* get(size_t i)       { assert(i < geometries.size()); return geometries[i].ptr; }
 | |
|     __forceinline const Geometry* get(size_t i) const { assert(i < geometries.size()); return geometries[i].ptr; }
 | |
| 
 | |
|     template<typename Mesh>
 | |
|       __forceinline       Mesh* get(size_t i)       { 
 | |
|       assert(i < geometries.size()); 
 | |
|       assert(geometries[i]->getTypeMask() & Mesh::geom_type);
 | |
|       return (Mesh*)geometries[i].ptr; 
 | |
|     }
 | |
|     template<typename Mesh>
 | |
|       __forceinline const Mesh* get(size_t i) const { 
 | |
|       assert(i < geometries.size()); 
 | |
|       assert(geometries[i]->getTypeMask() & Mesh::geom_type);
 | |
|       return (Mesh*)geometries[i].ptr; 
 | |
|     }
 | |
| 
 | |
|     template<typename Mesh>
 | |
|     __forceinline Mesh* getSafe(size_t i) {
 | |
|       assert(i < geometries.size());
 | |
|       if (geometries[i] == null) return nullptr;
 | |
|       if (!(geometries[i]->getTypeMask() & Mesh::geom_type)) return nullptr;
 | |
|       else return (Mesh*) geometries[i].ptr;
 | |
|     }
 | |
| 
 | |
|     __forceinline Ref<Geometry> get_locked(size_t i)  {
 | |
|       Lock<MutexSys> lock(geometriesMutex);
 | |
|       assert(i < geometries.size()); 
 | |
|       return geometries[i]; 
 | |
|     }
 | |
| 
 | |
|     /* flag decoding */
 | |
|     __forceinline bool isFastAccel() const { return !isCompactAccel() && !isRobustAccel(); }
 | |
|     __forceinline bool isCompactAccel() const { return scene_flags & RTC_SCENE_FLAG_COMPACT; }
 | |
|     __forceinline bool isRobustAccel()  const { return scene_flags & RTC_SCENE_FLAG_ROBUST; }
 | |
|     __forceinline bool isStaticAccel()  const { return !(scene_flags & RTC_SCENE_FLAG_DYNAMIC); }
 | |
|     __forceinline bool isDynamicAccel() const { return scene_flags & RTC_SCENE_FLAG_DYNAMIC; }
 | |
|     
 | |
|     __forceinline bool hasArgumentFilterFunction() const {
 | |
|       return scene_flags & RTC_SCENE_FLAG_FILTER_FUNCTION_IN_ARGUMENTS;
 | |
|     }
 | |
|     
 | |
|     __forceinline bool hasGeometryFilterFunction() {
 | |
|       return world.numFilterFunctions != 0;
 | |
|     }
 | |
|       
 | |
|     __forceinline bool hasFilterFunction() {
 | |
|       return hasArgumentFilterFunction() || hasGeometryFilterFunction();
 | |
|     }
 | |
|     
 | |
|     void* createQBVH6Accel();
 | |
| 
 | |
|   public:
 | |
|     Device* device;
 | |
| 
 | |
|   public:
 | |
|     IDPool<unsigned,0xFFFFFFFE> id_pool;
 | |
|     Device::vector<Ref<Geometry>> geometries = device; //!< list of all user geometries
 | |
|     avector<unsigned int> geometryModCounters_;
 | |
|     Device::vector<float*> vertices = device;
 | |
|     
 | |
|   public:
 | |
|     /* these are to detect if we need to recreate the acceleration structures */
 | |
|     bool flags_modified;
 | |
|     unsigned int enabled_geometry_types;
 | |
|     
 | |
|     RTCSceneFlags scene_flags;
 | |
|     RTCBuildQuality quality_flags;
 | |
|     MutexSys buildMutex;
 | |
|     MutexSys geometriesMutex;
 | |
| 
 | |
| #if defined(EMBREE_SYCL_SUPPORT)
 | |
|   public:
 | |
|     BBox3f hwaccel_bounds = empty;
 | |
|     AccelBuffer hwaccel;
 | |
| #endif
 | |
|     
 | |
|   private:
 | |
|     bool modified;                   //!< true if scene got modified
 | |
| 
 | |
|   public:
 | |
| 
 | |
|     std::unique_ptr<TaskGroup> taskGroup;
 | |
|     
 | |
|   public:
 | |
|     struct BuildProgressMonitorInterface : public BuildProgressMonitor {
 | |
|       BuildProgressMonitorInterface(Scene* scene) 
 | |
|       : scene(scene) {}
 | |
|       void operator() (size_t dn) const { scene->progressMonitor(double(dn)); }
 | |
|     private:
 | |
|       Scene* scene;
 | |
|     };
 | |
|     BuildProgressMonitorInterface progressInterface;
 | |
|     RTCProgressMonitorFunction progress_monitor_function;
 | |
|     void* progress_monitor_ptr;
 | |
|     std::atomic<size_t> progress_monitor_counter;
 | |
|     void progressMonitor(double nprims);
 | |
|     void setProgressMonitorFunction(RTCProgressMonitorFunction func, void* ptr);
 | |
| 
 | |
|   private:
 | |
|     GeometryCounts world;               //!< counts for geometry
 | |
| 
 | |
|   public:
 | |
| 
 | |
|     __forceinline size_t numPrimitives() const {
 | |
|       return world.size();
 | |
|     }
 | |
| 
 | |
|     __forceinline size_t getNumPrimitives(Geometry::GTypeMask mask, bool mblur) const
 | |
|     {
 | |
|       size_t count = 0;
 | |
|       
 | |
|       if (mask & Geometry::MTY_TRIANGLE_MESH)
 | |
|         count += mblur ? world.numMBTriangles : world.numTriangles;
 | |
|       
 | |
|       if (mask & Geometry::MTY_QUAD_MESH)
 | |
|         count += mblur ? world.numMBQuads : world.numQuads;
 | |
|       
 | |
|       if (mask & Geometry::MTY_CURVE2)
 | |
|         count += mblur ? world.numMBLineSegments : world.numLineSegments;
 | |
|       
 | |
|       if (mask & Geometry::MTY_CURVE4)
 | |
|         count += mblur ? world.numMBBezierCurves : world.numBezierCurves;
 | |
|       
 | |
|       if (mask & Geometry::MTY_POINTS)
 | |
|         count += mblur ? world.numMBPoints : world.numPoints;
 | |
|       
 | |
|       if (mask & Geometry::MTY_SUBDIV_MESH)
 | |
|         count += mblur ? world.numMBSubdivPatches : world.numSubdivPatches;
 | |
|       
 | |
|       if (mask & Geometry::MTY_USER_GEOMETRY)
 | |
|         count += mblur ? world.numMBUserGeometries : world.numUserGeometries;
 | |
|       
 | |
|       if (mask & Geometry::MTY_INSTANCE_CHEAP)
 | |
|         count += mblur ? world.numMBInstancesCheap : world.numInstancesCheap;
 | |
|       
 | |
|       if (mask & Geometry::MTY_INSTANCE_EXPENSIVE)
 | |
|         count += mblur  ? world.numMBInstancesExpensive : world.numInstancesExpensive;
 | |
| 
 | |
|       if (mask & Geometry::MTY_INSTANCE_ARRAY)
 | |
|         count += mblur  ? world.numMBInstanceArrays : world.numInstanceArrays;
 | |
| 
 | |
|       if (mask & Geometry::MTY_GRID_MESH)
 | |
|         count += mblur  ? world.numMBGrids : world.numGrids;
 | |
|       
 | |
|       return count;
 | |
|     }
 | |
| 
 | |
|     __forceinline size_t getNumSubPrimitives(Geometry::GTypeMask mask, bool mblur) const
 | |
|     {
 | |
|       size_t count = 0;
 | |
|       
 | |
|       if (mask & Geometry::MTY_GRID_MESH)
 | |
|         count += mblur  ? world.numMBSubGrids : world.numSubGrids;
 | |
| 
 | |
|       Geometry::GTypeMask new_mask = (Geometry::GTypeMask)(mask & ~Geometry::MTY_GRID_MESH);
 | |
|       count += getNumPrimitives(new_mask, mblur);
 | |
|       
 | |
|       return count;
 | |
|     }
 | |
|     
 | |
|     template<typename Mesh, bool mblur>
 | |
|     __forceinline unsigned getNumTimeSteps()
 | |
|     {
 | |
|       if (!mblur)
 | |
|         return 1;
 | |
| 
 | |
|       Scene::Iterator<Mesh,mblur> iter(this);
 | |
|       return iter.maxTimeStepsPerGeometry();
 | |
|     }
 | |
| 
 | |
|     template<typename Mesh, bool mblur>
 | |
|     __forceinline unsigned int getMaxGeomID()
 | |
|     {
 | |
|       Scene::Iterator<Mesh,mblur> iter(this);
 | |
|       return iter.maxGeomID();
 | |
|     }
 | |
|   };
 | |
| }
 |